]>
Commit | Line | Data |
---|---|---|
1 | /****************************************************************************** | |
2 | * Copyright © 2014-2018 The SuperNET Developers. * | |
3 | * * | |
4 | * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * | |
5 | * the top-level directory of this distribution for the individual copyright * | |
6 | * holder information and the developer policies on copyright and licensing. * | |
7 | * * | |
8 | * Unless otherwise agreed in a custom licensing agreement, no part of the * | |
9 | * SuperNET software, including this file may be copied, modified, propagated * | |
10 | * or distributed except according to the terms contained in the LICENSE file * | |
11 | * * | |
12 | * Removal or modification of this copyright notice is prohibited. * | |
13 | * * | |
14 | ******************************************************************************/ | |
15 | ||
16 | // komodo functions that interact with bitcoind C++ | |
17 | ||
18 | #ifdef _WIN32 | |
19 | #include <curl/curl.h> | |
20 | #include <curl/easy.h> | |
21 | #else | |
22 | #include <curl/curl.h> | |
23 | #include <curl/easy.h> | |
24 | #endif | |
25 | ||
26 | #include "komodo_defs.h" | |
27 | ||
28 | int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); | |
29 | int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); | |
30 | ||
31 | //#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) | |
32 | ||
33 | struct MemoryStruct { char *memory; size_t size; }; | |
34 | struct return_string { char *ptr; size_t len; }; | |
35 | ||
36 | // return data from the server | |
37 | #define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) | |
38 | #define CURL_GLOBAL_SSL (1<<0) | |
39 | #define CURL_GLOBAL_WIN32 (1<<1) | |
40 | ||
41 | ||
42 | /************************************************************************ | |
43 | * | |
44 | * Initialize the string handler so that it is thread safe | |
45 | * | |
46 | ************************************************************************/ | |
47 | ||
48 | void init_string(struct return_string *s) | |
49 | { | |
50 | s->len = 0; | |
51 | s->ptr = (char *)calloc(1,s->len+1); | |
52 | if ( s->ptr == NULL ) | |
53 | { | |
54 | fprintf(stderr,"init_string malloc() failed\n"); | |
55 | exit(-1); | |
56 | } | |
57 | s->ptr[0] = '\0'; | |
58 | } | |
59 | ||
60 | /************************************************************************ | |
61 | * | |
62 | * Use the "writer" to accumulate text until done | |
63 | * | |
64 | ************************************************************************/ | |
65 | ||
66 | size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s) | |
67 | { | |
68 | size_t new_len = s->len + size*nmemb; | |
69 | s->ptr = (char *)realloc(s->ptr,new_len+1); | |
70 | if ( s->ptr == NULL ) | |
71 | { | |
72 | fprintf(stderr, "accumulate realloc() failed\n"); | |
73 | exit(-1); | |
74 | } | |
75 | memcpy(s->ptr+s->len,ptr,size*nmemb); | |
76 | s->ptr[new_len] = '\0'; | |
77 | s->len = new_len; | |
78 | return(size * nmemb); | |
79 | } | |
80 | ||
81 | /************************************************************************ | |
82 | * | |
83 | * return the current system time in milliseconds | |
84 | * | |
85 | ************************************************************************/ | |
86 | ||
87 | #define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field | |
88 | #ifdef EXTRACT_BITCOIND_RESULT | |
89 | ||
90 | /************************************************************************ | |
91 | * | |
92 | * perform post processing of the results | |
93 | * | |
94 | ************************************************************************/ | |
95 | ||
96 | char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params) | |
97 | { | |
98 | long i,j,len; char *retstr = 0; cJSON *json,*result,*error; | |
99 | //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); | |
100 | if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 ) | |
101 | { | |
102 | if ( strcmp(command,"signrawtransaction") != 0 ) | |
103 | printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); | |
104 | return(rpcstr); | |
105 | } | |
106 | json = cJSON_Parse(rpcstr); | |
107 | if ( json == 0 ) | |
108 | { | |
109 | printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params); | |
110 | free(rpcstr); | |
111 | return(0); | |
112 | } | |
113 | result = cJSON_GetObjectItem(json,"result"); | |
114 | error = cJSON_GetObjectItem(json,"error"); | |
115 | if ( error != 0 && result != 0 ) | |
116 | { | |
117 | if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) | |
118 | { | |
119 | retstr = cJSON_Print(result); | |
120 | len = strlen(retstr); | |
121 | if ( retstr[0] == '"' && retstr[len-1] == '"' ) | |
122 | { | |
123 | for (i=1,j=0; i<len-1; i++,j++) | |
124 | retstr[j] = retstr[i]; | |
125 | retstr[j] = 0; | |
126 | } | |
127 | } | |
128 | else if ( (error->type&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL ) | |
129 | { | |
130 | if ( strcmp(command,"signrawtransaction") != 0 ) | |
131 | printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr); | |
132 | } | |
133 | free(rpcstr); | |
134 | } else retstr = rpcstr; | |
135 | free_json(json); | |
136 | //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); | |
137 | return(retstr); | |
138 | } | |
139 | #endif | |
140 | ||
141 | /************************************************************************ | |
142 | * | |
143 | * perform the query | |
144 | * | |
145 | ************************************************************************/ | |
146 | ||
147 | char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) | |
148 | { | |
149 | static int didinit,count,count2; static double elapsedsum,elapsedsum2; | |
150 | struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; | |
151 | char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; | |
152 | if ( didinit == 0 ) | |
153 | { | |
154 | didinit = 1; | |
155 | curl_global_init(CURL_GLOBAL_ALL); //init the curl session | |
156 | } | |
157 | numretries = 0; | |
158 | if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 ) | |
159 | specialcase = 1; | |
160 | else specialcase = 0; | |
161 | if ( url[0] == 0 ) | |
162 | strcpy(url,"http://127.0.0.1:7876/nxt"); | |
163 | if ( specialcase != 0 && 0 ) | |
164 | printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); | |
165 | try_again: | |
166 | if ( retstrp != 0 ) | |
167 | *retstrp = 0; | |
168 | starttime = OS_milliseconds(); | |
169 | curl_handle = curl_easy_init(); | |
170 | init_string(&s); | |
171 | headers = curl_slist_append(0,"Expect:"); | |
172 | ||
173 | curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); | |
174 | curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); | |
175 | curl_easy_setopt(curl_handle,CURLOPT_URL, url); | |
176 | curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function | |
177 | curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback | |
178 | curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash | |
179 | curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback | |
180 | if ( strncmp(url,"https",5) == 0 ) | |
181 | { | |
182 | curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); | |
183 | curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0); | |
184 | } | |
185 | if ( userpass != 0 ) | |
186 | curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass); | |
187 | databuf = 0; | |
188 | if ( params != 0 ) | |
189 | { | |
190 | if ( command != 0 && specialcase == 0 ) | |
191 | { | |
192 | len = strlen(params); | |
193 | if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) { | |
194 | bracket0 = bracket1 = (char *)""; | |
195 | } | |
196 | else | |
197 | { | |
198 | bracket0 = (char *)"["; | |
199 | bracket1 = (char *)"]"; | |
200 | } | |
201 | ||
202 | databuf = (char *)malloc(256 + strlen(command) + strlen(params)); | |
203 | sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); | |
204 | //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf); | |
205 | // | |
206 | } //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params); | |
207 | curl_easy_setopt(curl_handle,CURLOPT_POST,1L); | |
208 | if ( databuf != 0 ) | |
209 | curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf); | |
210 | else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params); | |
211 | } | |
212 | //laststart = milliseconds(); | |
213 | res = curl_easy_perform(curl_handle); | |
214 | curl_slist_free_all(headers); | |
215 | curl_easy_cleanup(curl_handle); | |
216 | if ( databuf != 0 ) // clean up temporary buffer | |
217 | { | |
218 | free(databuf); | |
219 | databuf = 0; | |
220 | } | |
221 | if ( res != CURLE_OK ) | |
222 | { | |
223 | numretries++; | |
224 | if ( specialcase != 0 ) | |
225 | { | |
226 | printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); | |
227 | free(s.ptr); | |
228 | return(0); | |
229 | } | |
230 | else if ( numretries >= 1 ) | |
231 | { | |
232 | //printf("Maximum number of retries exceeded!\n"); | |
233 | free(s.ptr); | |
234 | return(0); | |
235 | } | |
236 | if ( (rand() % 1000) == 0 ) | |
237 | printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); | |
238 | free(s.ptr); | |
239 | sleep((1<<numretries)); | |
240 | goto try_again; | |
241 | ||
242 | } | |
243 | else | |
244 | { | |
245 | if ( command != 0 && specialcase == 0 ) | |
246 | { | |
247 | count++; | |
248 | elapsedsum += (OS_milliseconds() - starttime); | |
249 | if ( (count % 1000000) == 0) | |
250 | printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url); | |
251 | if ( retstrp != 0 ) | |
252 | { | |
253 | *retstrp = s.ptr; | |
254 | return(s.ptr); | |
255 | } | |
256 | return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params)); | |
257 | } | |
258 | else | |
259 | { | |
260 | if ( 0 && specialcase != 0 ) | |
261 | fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr); | |
262 | count2++; | |
263 | elapsedsum2 += (OS_milliseconds() - starttime); | |
264 | if ( (count2 % 10000) == 0) | |
265 | printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command); | |
266 | return(s.ptr); | |
267 | } | |
268 | } | |
269 | printf("bitcoind_RPC: impossible case\n"); | |
270 | free(s.ptr); | |
271 | return(0); | |
272 | } | |
273 | ||
274 | static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data) | |
275 | { | |
276 | size_t realsize = (size * nmemb); | |
277 | struct MemoryStruct *mem = (struct MemoryStruct *)data; | |
278 | mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1)); | |
279 | if ( mem->memory != 0 ) | |
280 | { | |
281 | if ( ptr != 0 ) | |
282 | memcpy(&(mem->memory[mem->size]),ptr,realsize); | |
283 | mem->size += realsize; | |
284 | mem->memory[mem->size] = 0; | |
285 | } | |
286 | //printf("got %d bytes\n",(int32_t)(size*nmemb)); | |
287 | return(realsize); | |
288 | } | |
289 | ||
290 | char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3) | |
291 | { | |
292 | struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0; | |
293 | if ( (cHandle= *cHandlep) == NULL ) | |
294 | *cHandlep = cHandle = curl_easy_init(); | |
295 | else curl_easy_reset(cHandle); | |
296 | //#ifdef DEBUG | |
297 | //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1); | |
298 | //#endif | |
299 | curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); | |
300 | curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0); | |
301 | //curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1); | |
302 | curl_easy_setopt(cHandle,CURLOPT_URL,url); | |
303 | curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10); | |
304 | if ( userpass != 0 && userpass[0] != 0 ) | |
305 | curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass); | |
306 | if ( postfields != 0 && postfields[0] != 0 ) | |
307 | { | |
308 | curl_easy_setopt(cHandle,CURLOPT_POST,1); | |
309 | curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields); | |
310 | } | |
311 | if ( hdr0 != NULL && hdr0[0] != 0 ) | |
312 | { | |
313 | //printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:""); | |
314 | headers = curl_slist_append(headers,hdr0); | |
315 | if ( hdr1 != 0 && hdr1[0] != 0 ) | |
316 | headers = curl_slist_append(headers,hdr1); | |
317 | if ( hdr2 != 0 && hdr2[0] != 0 ) | |
318 | headers = curl_slist_append(headers,hdr2); | |
319 | if ( hdr3 != 0 && hdr3[0] != 0 ) | |
320 | headers = curl_slist_append(headers,hdr3); | |
321 | } //headers = curl_slist_append(0,"Expect:"); | |
322 | if ( headers != 0 ) | |
323 | curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers); | |
324 | //res = curl_easy_perform(cHandle); | |
325 | memset(&chunk,0,sizeof(chunk)); | |
326 | curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback); | |
327 | curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk); | |
328 | curl_easy_perform(cHandle); | |
329 | curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code); | |
330 | if ( headers != 0 ) | |
331 | curl_slist_free_all(headers); | |
332 | if ( code != 200 ) | |
333 | printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory); | |
334 | return(chunk.memory); | |
335 | } | |
336 | ||
337 | char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) | |
338 | { | |
339 | //static void *cHandle; | |
340 | char url[512],*retstr=0,*retstr2=0,postdata[8192]; | |
341 | if ( params == 0 || params[0] == 0 ) | |
342 | params = (char *)"[]"; | |
343 | if ( strlen(params) < sizeof(postdata)-128 ) | |
344 | { | |
345 | sprintf(url,(char *)"http://127.0.0.1:%u",port); | |
346 | sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); | |
347 | //printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS); | |
348 | retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); | |
349 | //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); | |
350 | } | |
351 | return(retstr2); | |
352 | } | |
353 | ||
354 | int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp) | |
355 | { | |
356 | char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0; | |
357 | params[0] = 0; | |
358 | *kmdnotarized_heightp = 0; | |
359 | if ( strcmp(dest,"KMD") == 0 ) | |
360 | { | |
361 | port = KMD_PORT; | |
362 | userpass = KMDUSERPASS; | |
363 | } | |
364 | else if ( strcmp(dest,"BTC") == 0 ) | |
365 | { | |
366 | port = 8332; | |
367 | userpass = BTCUSERPASS; | |
368 | } | |
369 | else return(0); | |
370 | if ( userpass[0] != 0 ) | |
371 | { | |
372 | if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 ) | |
373 | { | |
374 | //printf("(%s)\n",jsonstr); | |
375 | if ( (json= cJSON_Parse(jsonstr)) != 0 ) | |
376 | { | |
377 | if ( (item= jobj(json,(char *)"result")) != 0 ) | |
378 | { | |
379 | height = jint(item,(char *)"blocks"); | |
380 | *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height; | |
381 | } | |
382 | free_json(json); | |
383 | } | |
384 | free(jsonstr); | |
385 | } | |
386 | sprintf(params,"[\"%s\", 1]",txidstr); | |
387 | if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 ) | |
388 | { | |
389 | //printf("(%s)\n",jsonstr); | |
390 | if ( (json= cJSON_Parse(jsonstr)) != 0 ) | |
391 | { | |
392 | if ( (item= jobj(json,(char *)"result")) != 0 ) | |
393 | { | |
394 | txid_confirmations = jint(item,(char *)"confirmations"); | |
395 | if ( txid_confirmations > 0 && height > txid_confirmations ) | |
396 | txid_height = height - txid_confirmations; | |
397 | else txid_height = height; | |
398 | //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height); | |
399 | } | |
400 | free_json(json); | |
401 | } | |
402 | free(jsonstr); | |
403 | } | |
404 | } | |
405 | return(txid_height); | |
406 | } | |
407 | ||
408 | int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH) | |
409 | { | |
410 | int32_t i; uint256 hash; char params[256]; | |
411 | for (i=0; i<32; i++) | |
412 | ((uint8_t *)&hash)[i] = script[2+i]; | |
413 | if ( hash == NOTARIZED_HASH ) | |
414 | return(0); | |
415 | for (i=0; i<32; i++) | |
416 | printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]); | |
417 | printf(" notarized, "); | |
418 | for (i=0; i<32; i++) | |
419 | printf("%02x",((uint8_t *)&hash)[i]); | |
420 | printf(" opreturn from [%s] ht.%d MISMATCHED\n",ASSETCHAINS_SYMBOL,height); | |
421 | return(-1); | |
422 | } | |
423 | ||
424 | int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) | |
425 | { | |
426 | char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; | |
427 | script = _script; | |
428 | /*params[0] = '['; | |
429 | params[1] = '"'; | |
430 | for (i=0; i<32; i++) | |
431 | sprintf(¶ms[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]); | |
432 | strcat(params,"\", 1]");*/ | |
433 | sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str()); | |
434 | if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) | |
435 | return(0); | |
436 | if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) | |
437 | printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT); | |
438 | if ( strcmp(dest,"KMD") == 0 ) | |
439 | { | |
440 | if ( KMDUSERPASS[0] != 0 ) | |
441 | { | |
442 | if ( ASSETCHAINS_SYMBOL[0] != 0 ) | |
443 | { | |
444 | jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); | |
445 | //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr); | |
446 | } | |
447 | }//else jsonstr = _dex_getrawtransaction(); | |
448 | else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok | |
449 | } | |
450 | else if ( strcmp(dest,"BTC") == 0 ) | |
451 | { | |
452 | if ( BTCUSERPASS[0] != 0 ) | |
453 | { | |
454 | //printf("BTCUSERPASS.(%s)\n",BTCUSERPASS); | |
455 | jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,8332); | |
456 | } | |
457 | //else jsonstr = _dex_getrawtransaction(); | |
458 | else return(0); | |
459 | } | |
460 | else | |
461 | { | |
462 | printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest); | |
463 | return(-1); | |
464 | } | |
465 | if ( jsonstr != 0 ) | |
466 | { | |
467 | if ( (json= cJSON_Parse(jsonstr)) != 0 ) | |
468 | { | |
469 | if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 ) | |
470 | { | |
471 | vout = jitem(vouts,n-1); | |
472 | if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) | |
473 | printf("vout.(%s)\n",jprint(vout,0)); | |
474 | if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 ) | |
475 | { | |
476 | if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) | |
477 | { | |
478 | //printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str()); | |
479 | len = strlen(hexstr) >> 1; | |
480 | decode_hex(script,len,hexstr); | |
481 | if ( script[1] == 0x4c ) | |
482 | { | |
483 | script++; | |
484 | len--; | |
485 | } | |
486 | else if ( script[1] == 0x4d ) | |
487 | { | |
488 | script += 2; | |
489 | len -= 2; | |
490 | } | |
491 | retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH); | |
492 | } | |
493 | } | |
494 | } | |
495 | free_json(txjson); | |
496 | } | |
497 | free(jsonstr); | |
498 | } | |
499 | return(retval); | |
500 | } | |
501 | ||
502 | /*uint256 komodo_getblockhash(int32_t height) | |
503 | { | |
504 | uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32]; | |
505 | memset(&hash,0,sizeof(hash)); | |
506 | sprintf(params,"[%d]",height); | |
507 | if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_PORT)) != 0 ) | |
508 | { | |
509 | if ( (result= cJSON_Parse(jsonstr)) != 0 ) | |
510 | { | |
511 | if ( (hexstr= jstr(result,(char *)"result")) != 0 ) | |
512 | { | |
513 | if ( is_hexstr(hexstr,0) == 64 ) | |
514 | { | |
515 | decode_hex(revbuf,32,hexstr); | |
516 | for (i=0; i<32; i++) | |
517 | ((uint8_t *)&hash)[i] = revbuf[31-i]; | |
518 | } | |
519 | } | |
520 | free_json(result); | |
521 | } | |
522 | printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash); | |
523 | free(jsonstr); | |
524 | } | |
525 | return(hash); | |
526 | } | |
527 | ||
528 | uint256 _komodo_getblockhash(int32_t height);*/ | |
529 | ||
530 | uint64_t komodo_seed(int32_t height) | |
531 | { | |
532 | uint64_t seed = 0; | |
533 | /*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds... | |
534 | { | |
535 | uint256 hash,zero; CBlockIndex *pindex; | |
536 | memset(&hash,0,sizeof(hash)); | |
537 | memset(&zero,0,sizeof(zero)); | |
538 | if ( height > 10 ) | |
539 | height -= 10; | |
540 | if ( ASSETCHAINS_SYMBOL[0] == 0 ) | |
541 | hash = _komodo_getblockhash(height); | |
542 | if ( memcmp(&hash,&zero,sizeof(hash)) == 0 ) | |
543 | hash = komodo_getblockhash(height); | |
544 | int32_t i; | |
545 | for (i=0; i<32; i++) | |
546 | printf("%02x",((uint8_t *)&hash)[i]); | |
547 | printf(" seed.%d\n",height); | |
548 | seed = arith_uint256(hash.GetHex()).GetLow64(); | |
549 | } | |
550 | else*/ | |
551 | { | |
552 | seed = (height << 13) ^ (height << 2); | |
553 | seed <<= 21; | |
554 | seed |= (height & 0xffffffff); | |
555 | seed ^= (seed << 17) ^ (seed << 1); | |
556 | } | |
557 | return(seed); | |
558 | } | |
559 | ||
560 | uint32_t komodo_txtime(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr) | |
561 | { | |
562 | CTxDestination address; CTransaction tx; uint256 hashBlock; | |
563 | *valuep = 0; | |
564 | if (!GetTransaction(hash, tx, | |
565 | #ifndef KOMODO_ZCASH | |
566 | Params().GetConsensus(), | |
567 | #endif | |
568 | hashBlock, true)) | |
569 | { | |
570 | fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); | |
571 | return(0); | |
572 | } | |
573 | //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); | |
574 | if ( n < tx.vout.size() ) | |
575 | { | |
576 | *valuep = tx.vout[n].nValue; | |
577 | if (ExtractDestination(tx.vout[n].scriptPubKey, address)) | |
578 | strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); | |
579 | } | |
580 | return(tx.nLockTime); | |
581 | } | |
582 | ||
583 | void komodo_disconnect(CBlockIndex *pindex,CBlock& block) | |
584 | { | |
585 | char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; | |
586 | //fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight); | |
587 | komodo_init(pindex->nHeight); | |
588 | if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) | |
589 | { | |
590 | //sp->rewinding = pindex->nHeight; | |
591 | //fprintf(stderr,"-%d ",pindex->nHeight); | |
592 | } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL); | |
593 | } | |
594 | ||
595 | ||
596 | int32_t komodo_is_notarytx(const CTransaction& tx) | |
597 | { | |
598 | uint8_t *ptr; static uint8_t crypto777[33]; | |
599 | if ( tx.vout.size() > 0 ) | |
600 | { | |
601 | #ifdef KOMODO_ZCASH | |
602 | ptr = (uint8_t *)tx.vout[0].scriptPubKey.data(); | |
603 | #else | |
604 | ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0]; | |
605 | #endif | |
606 | if ( ptr != 0 ) | |
607 | { | |
608 | if ( crypto777[0] == 0 ) | |
609 | decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); | |
610 | if ( memcmp(ptr+1,crypto777,33) == 0 ) | |
611 | { | |
612 | //printf("found notarytx\n"); | |
613 | return(1); | |
614 | } | |
615 | } | |
616 | } | |
617 | return(0); | |
618 | } | |
619 | ||
620 | int32_t komodo_block2height(CBlock *block) | |
621 | { | |
622 | static uint32_t match,mismatch; | |
623 | int32_t i,n,height2=-1,height = 0; uint8_t *ptr; CBlockIndex *pindex; | |
624 | if ( (pindex= mapBlockIndex[block->GetHash()]) != 0 ) | |
625 | { | |
626 | height2 = (int32_t)pindex->nHeight; | |
627 | if ( height2 >= 0 ) | |
628 | return(height2); | |
629 | } | |
630 | if ( block->vtx[0].vin.size() > 0 ) | |
631 | { | |
632 | #ifdef KOMODO_ZCASH | |
633 | ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data(); | |
634 | #else | |
635 | ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0]; | |
636 | #endif | |
637 | if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 ) | |
638 | { | |
639 | //for (i=0; i<6; i++) | |
640 | // printf("%02x",ptr[i]); | |
641 | n = ptr[0]; | |
642 | for (i=0; i<n; i++) // looks strange but this works | |
643 | { | |
644 | //03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256 | |
645 | height += ((uint32_t)ptr[i+1] << (i*8)); | |
646 | //printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height); | |
647 | } | |
648 | //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height); | |
649 | } | |
650 | //komodo_init(height); | |
651 | } | |
652 | if ( height != height2 ) | |
653 | { | |
654 | fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch); | |
655 | mismatch++; | |
656 | if ( height2 >= 0 ) | |
657 | height = height2; | |
658 | } else match++; | |
659 | return(height); | |
660 | } | |
661 | ||
662 | void komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) | |
663 | { | |
664 | int32_t n; | |
665 | if ( KOMODO_LOADINGBLOCKS == 0 ) | |
666 | memset(pubkey33,0xff,33); | |
667 | else memset(pubkey33,0,33); | |
668 | if ( block->vtx[0].vout.size() > 0 ) | |
669 | { | |
670 | #ifdef KOMODO_ZCASH | |
671 | uint8_t *ptr = (uint8_t *)block->vtx[0].vout[0].scriptPubKey.data(); | |
672 | #else | |
673 | uint8_t *ptr = (uint8_t *)&block->vtx[0].vout[0].scriptPubKey[0]; | |
674 | #endif | |
675 | //komodo_init(0); | |
676 | n = block->vtx[0].vout[0].scriptPubKey.size(); | |
677 | if ( n == 35 ) | |
678 | memcpy(pubkey33,ptr+1,33); | |
679 | } | |
680 | } | |
681 | ||
682 | int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) | |
683 | { | |
684 | block.SetNull(); | |
685 | // Open history file to read | |
686 | CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION); | |
687 | if (filein.IsNull()) | |
688 | return(-1); | |
689 | // Read block | |
690 | try { filein >> block; } | |
691 | catch (const std::exception& e) | |
692 | { | |
693 | fprintf(stderr,"readblockfromdisk err B\n"); | |
694 | return(-1); | |
695 | } | |
696 | return(0); | |
697 | } | |
698 | ||
699 | uint32_t komodo_chainactive_timestamp() | |
700 | { | |
701 | if ( chainActive.Tip() != 0 ) | |
702 | return((uint32_t)chainActive.Tip()->GetBlockTime()); | |
703 | else return(0); | |
704 | } | |
705 | ||
706 | CBlockIndex *komodo_chainactive(int32_t height) | |
707 | { | |
708 | if ( chainActive.Tip() != 0 ) | |
709 | { | |
710 | if ( height <= chainActive.Tip()->nHeight ) | |
711 | return(chainActive[height]); | |
712 | // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight); | |
713 | } | |
714 | //fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height); | |
715 | return(0); | |
716 | } | |
717 | ||
718 | uint32_t komodo_heightstamp(int32_t height) | |
719 | { | |
720 | CBlockIndex *ptr; | |
721 | if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) | |
722 | return(ptr->nTime); | |
723 | //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height); | |
724 | return(0); | |
725 | } | |
726 | ||
727 | void komodo_pindex_init(CBlockIndex *pindex,int32_t height) | |
728 | { | |
729 | int32_t i,num; uint8_t pubkeys[64][33]; CBlock block; | |
730 | if ( pindex->didinit != 0 ) | |
731 | return; | |
732 | //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->nHeight,pindex->notaryid,height); | |
733 | if ( pindex->didinit == 0 ) | |
734 | { | |
735 | pindex->notaryid = -1; | |
736 | if ( KOMODO_LOADINGBLOCKS == 0 ) | |
737 | memset(pindex->pubkey33,0xff,33); | |
738 | else memset(pindex->pubkey33,0,33); | |
739 | if ( komodo_blockload(block,pindex) == 0 ) | |
740 | { | |
741 | komodo_block2pubkey33(pindex->pubkey33,&block); | |
742 | //for (i=0; i<33; i++) | |
743 | // fprintf(stderr,"%02x",pindex->pubkey33[i]); | |
744 | //fprintf(stderr," set pubkey at height %d/%d\n",pindex->nHeight,height); | |
745 | //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 ) | |
746 | pindex->didinit = (KOMODO_LOADINGBLOCKS == 0); | |
747 | } // else fprintf(stderr,"error loading block at %d/%d",pindex->nHeight,height); | |
748 | } | |
749 | if ( pindex->didinit != 0 && pindex->nHeight >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->nHeight,(uint32_t)pindex->nTime)) > 0 ) | |
750 | { | |
751 | for (i=0; i<num; i++) | |
752 | { | |
753 | if ( memcmp(pubkeys[i],pindex->pubkey33,33) == 0 ) | |
754 | { | |
755 | pindex->notaryid = i; | |
756 | break; | |
757 | } | |
758 | } | |
759 | if ( 0 && i == num ) | |
760 | { | |
761 | for (i=0; i<33; i++) | |
762 | fprintf(stderr,"%02x",pindex->pubkey33[i]); | |
763 | fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->nHeight,height); | |
764 | } | |
765 | } | |
766 | } | |
767 | ||
768 | void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) | |
769 | { | |
770 | int32_t num,i; //CBlock block; | |
771 | memset(pubkey33,0,33); | |
772 | if ( pindex != 0 ) | |
773 | { | |
774 | /*if ( komodo_blockload(block,pindex) == 0 ) | |
775 | { | |
776 | komodo_block2pubkey33(pindex->pubkey33,&block); | |
777 | return; | |
778 | }*/ | |
779 | if ( pindex->didinit != 0 ) | |
780 | { | |
781 | memcpy(pubkey33,pindex->pubkey33,33); | |
782 | return; | |
783 | } | |
784 | komodo_pindex_init(pindex,height); | |
785 | memcpy(pubkey33,pindex->pubkey33,33); | |
786 | } | |
787 | } | |
788 | ||
789 | /*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33) | |
790 | { | |
791 | int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33]; | |
792 | if ( (pindex= chainActive[height]) != 0 ) | |
793 | { | |
794 | if ( pindex->didinit != 0 ) | |
795 | { | |
796 | if ( destpubkey33 != 0 ) | |
797 | memcpy(destpubkey33,pindex->pubkey33,33); | |
798 | return(pindex->notaryid); | |
799 | } | |
800 | komodo_index2pubkey33(pubkey33,pindex,height); | |
801 | if ( destpubkey33 != 0 ) | |
802 | memcpy(destpubkey33,pindex->pubkey33,33); | |
803 | if ( pindex->didinit != 0 ) | |
804 | return(pindex->notaryid); | |
805 | timestamp = pindex->GetBlockTime(); | |
806 | if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 ) | |
807 | { | |
808 | for (i=0; i<num; i++) | |
809 | if ( memcmp(pubkeys[i],pubkey33,33) == 0 ) | |
810 | return(i); | |
811 | } | |
812 | } | |
813 | fprintf(stderr,"komodo_minerid height.%d null pindex\n",height); | |
814 | return(komodo_electednotary(&numnotaries,pubkey33,height,timestamp)); | |
815 | }*/ | |
816 | ||
817 | int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,int32_t *nonzpkeysp,int32_t height) | |
818 | { | |
819 | int32_t i,j,n,duplicate; CBlock block; CBlockIndex *pindex; uint8_t pubkey33[33],notarypubs[64][33]; | |
820 | memset(mids,-1,sizeof(*mids)*66); | |
821 | n = komodo_notaries(notarypubs,height,0); | |
822 | for (i=duplicate=0; i<66; i++) | |
823 | { | |
824 | if ( (pindex= komodo_chainactive(height-i)) != 0 ) | |
825 | { | |
826 | if ( komodo_blockload(block,pindex) == 0 ) | |
827 | { | |
828 | komodo_block2pubkey33(pubkeys[i],&block); | |
829 | for (j=0; j<n; j++) | |
830 | { | |
831 | if ( memcmp(pubkey33,pubkeys[j],33) == 0 ) | |
832 | { | |
833 | mids[i] = j; | |
834 | (*nonzpkeysp)++; | |
835 | break; | |
836 | } | |
837 | } | |
838 | } | |
839 | /*if ( pindex->didinit != 0 && (pindex->notaryid >= 64 || pindex->notaryid < -1) ) | |
840 | { | |
841 | fprintf(stderr,"unexpected notaryid.%d at ht.%d\n",pindex->notaryid,height-i); | |
842 | pindex->notaryid = -1; | |
843 | memset(pindex->pubkey33,0,33); | |
844 | pindex->didinit = 0; | |
845 | komodo_pindex_init(pindex,height); | |
846 | } | |
847 | if ( pindex->notaryid >= 0 && pindex->didinit != 0 ) | |
848 | { | |
849 | memcpy(pubkeys[i],pindex->pubkey33,33); | |
850 | mids[i] = pindex->notaryid; | |
851 | (*nonzpkeysp)++; | |
852 | } | |
853 | else | |
854 | { | |
855 | komodo_pindex_init(pindex,height-i); | |
856 | if ( pindex->didinit == 0 ) | |
857 | { | |
858 | if ( komodo_blockload(block,pindex) == 0 ) | |
859 | komodo_block2pubkey33(pubkeys[i],&block); | |
860 | } else memcpy(pubkeys[i],pindex->pubkey33,33); | |
861 | if ( (mids[i]= komodo_minerid(height-i,0)) >= 0 ) | |
862 | { | |
863 | //mids[i] = *(int32_t *)pubkey33; | |
864 | (*nonzpkeysp)++; | |
865 | } | |
866 | }*/ | |
867 | if ( mids[0] >= 0 && i > 0 && mids[i] == mids[0] ) | |
868 | duplicate++; | |
869 | } | |
870 | } | |
871 | if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) ) | |
872 | return(1); | |
873 | else return(0); | |
874 | } | |
875 | ||
876 | int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) // deprecate | |
877 | { | |
878 | /*int32_t i,n=0; | |
879 | for (i=0; i<width; i++,n++) | |
880 | { | |
881 | if ( height-i <= 0 ) | |
882 | break; | |
883 | minerids[i] = komodo_minerid(height - i,0); | |
884 | } | |
885 | return(n);*/ | |
886 | fprintf(stderr,"komodo_minerids is deprecated\n"); | |
887 | return(-1); | |
888 | } | |
889 | ||
890 | int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],int32_t height,uint8_t pubkey33[33],uint32_t timestamp) | |
891 | { | |
892 | int32_t i,notaryid=0,minerid,limit,nid; | |
893 | if ( height >= 700000 ) | |
894 | { | |
895 | if ( mids[0] >= 0 ) | |
896 | { | |
897 | for (i=1; i<66; i++) | |
898 | { | |
899 | if ( mids[i] == mids[0] ) | |
900 | { | |
901 | fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,mids[0],i); | |
902 | if ( height > 792000 ) | |
903 | return(-1); | |
904 | else break; | |
905 | } | |
906 | } | |
907 | return(1); | |
908 | } else return(0); | |
909 | } | |
910 | else | |
911 | { | |
912 | if ( height >= 225000 ) | |
913 | komodo_chosennotary(¬aryid,height,pubkey33,timestamp); | |
914 | if ( height >= 34000 && notaryid >= 0 ) | |
915 | { | |
916 | if ( height < 79693 ) | |
917 | limit = 64; | |
918 | else if ( height < 82000 ) | |
919 | limit = 8; | |
920 | else limit = 66; | |
921 | for (i=1; i<limit; i++) | |
922 | { | |
923 | komodo_chosennotary(&nid,height-i,pubkey33,timestamp); | |
924 | if ( nid == notaryid ) | |
925 | { | |
926 | //if ( (0) && notaryid > 0 ) | |
927 | fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d] nid.%d notaryid.%d\n",height,mids[0],i,nid,notaryid); | |
928 | if ( height > 225000 ) | |
929 | return(-1); | |
930 | } | |
931 | } | |
932 | //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit); | |
933 | return(1); | |
934 | } | |
935 | } | |
936 | return(0); | |
937 | } | |
938 | ||
939 | int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) | |
940 | { | |
941 | int32_t depth,notarized_ht; uint256 MoM,kmdtxid; | |
942 | depth = komodo_MoMdata(¬arized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip); | |
943 | memset(MoMp,0,sizeof(*MoMp)); | |
944 | memset(kmdtxidp,0,sizeof(*kmdtxidp)); | |
945 | *notarized_heightp = 0; | |
946 | if ( depth > 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) | |
947 | { | |
948 | *MoMp = MoM; | |
949 | *notarized_heightp = notarized_ht; | |
950 | *kmdtxidp = kmdtxid; | |
951 | } | |
952 | return(depth); | |
953 | } | |
954 | ||
955 | int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash) | |
956 | { | |
957 | int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex; | |
958 | if ( (pindex= chainActive.Tip()) == 0 ) | |
959 | return(-1); | |
960 | notarized_height = komodo_notarizeddata(pindex->nHeight,¬arized_hash,¬arized_desttxid); | |
961 | *notarized_heightp = notarized_height; | |
962 | if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 ) | |
963 | { | |
964 | //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str()); | |
965 | if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg | |
966 | { | |
967 | if ( nHeight < notarized_height ) | |
968 | { | |
969 | //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); | |
970 | return(-1); | |
971 | } | |
972 | else if ( nHeight == notarized_height && memcmp(&hash,¬arized_hash,sizeof(hash)) != 0 ) | |
973 | { | |
974 | fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); | |
975 | return(-1); | |
976 | } | |
977 | } else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->nHeight); | |
978 | } | |
979 | //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 ) | |
980 | // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight); | |
981 | return(0); | |
982 | } | |
983 | ||
984 | uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) | |
985 | { | |
986 | LOCK(cs_main); | |
987 | CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; | |
988 | *txheighttimep = *txheightp = *tiptimep = 0; | |
989 | *valuep = 0; | |
990 | if ( !GetTransaction(hash,tx,hashBlock,true) ) | |
991 | return(0); | |
992 | uint32_t locktime = 0; | |
993 | if ( n < tx.vout.size() ) | |
994 | { | |
995 | if ( (pindex= mapBlockIndex[hashBlock]) != 0 ) | |
996 | { | |
997 | *valuep = tx.vout[n].nValue; | |
998 | *txheightp = pindex->nHeight; | |
999 | *txheighttimep = pindex->nTime; | |
1000 | if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 ) | |
1001 | *tiptimep = (uint32_t)tipindex->nTime; | |
1002 | locktime = tx.nLockTime; | |
1003 | //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); | |
1004 | } | |
1005 | } | |
1006 | return(locktime); | |
1007 | } | |
1008 | ||
1009 | uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); | |
1010 | ||
1011 | uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight) | |
1012 | { | |
1013 | uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; | |
1014 | if ( (pindex= chainActive[tipheight]) != 0 ) | |
1015 | tiptime = (uint32_t)pindex->nTime; | |
1016 | else fprintf(stderr,"cant find height[%d]\n",tipheight); | |
1017 | if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 ) | |
1018 | { | |
1019 | if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) | |
1020 | return(komodo_interest(*txheightp,value,*locktimep,tiptime)); | |
1021 | //fprintf(stderr,"nValue %llu lock.%u:%u nTime.%u -> %llu\n",(long long)coins.vout[n].nValue,coins.nLockTime,timestamp,pindex->nTime,(long long)interest); | |
1022 | else fprintf(stderr,"komodo_accrued_interest value mismatch %llu vs %llu or height mismatch %d vs %d\n",(long long)value,(long long)checkvalue,*txheightp,checkheight); | |
1023 | } | |
1024 | return(0); | |
1025 | } | |
1026 | ||
1027 | int32_t komodo_isrealtime(int32_t *kmdheightp) | |
1028 | { | |
1029 | struct komodo_state *sp; CBlockIndex *pindex; | |
1030 | if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) | |
1031 | *kmdheightp = sp->CURRENT_HEIGHT; | |
1032 | else *kmdheightp = 0; | |
1033 | if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() ) | |
1034 | return(1); | |
1035 | else return(0); | |
1036 | } | |
1037 | ||
1038 | int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag) | |
1039 | { | |
1040 | uint32_t cmptime = nTime; | |
1041 | if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) | |
1042 | { | |
1043 | if ( txheight > 246748 ) | |
1044 | { | |
1045 | if ( txheight < 247205 ) | |
1046 | cmptime -= 16000; | |
1047 | if ( (int64_t)tx.nLockTime < cmptime-3600 ) | |
1048 | { | |
1049 | if ( tx.nLockTime != 1477258935 || dispflag != 0 ) | |
1050 | { | |
1051 | fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-3600)),(uint32_t)tx.nLockTime,cmptime); | |
1052 | } | |
1053 | return(-1); | |
1054 | } | |
1055 | if ( 0 && dispflag != 0 ) | |
1056 | fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-3600)),(int32_t)tx.nLockTime,cmptime); | |
1057 | } | |
1058 | } | |
1059 | return(0); | |
1060 | } | |
1061 |