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