]> Git Repo - VerusCoin.git/blob - src/komodo_bitcoind.h
fd257cb0a0f4c77b564d0fd69614f0a7fa40ec1a
[VerusCoin.git] / src / komodo_bitcoind.h
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(&params[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) gets data corrupted
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             komodo_block2pubkey33(pubkey33,&block);
776     }
777 }
778
779 /*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33)
780 {
781     int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33];
782     if ( (pindex= chainActive[height]) != 0 )
783     {
784         if ( pindex->didinit != 0 )
785         {
786             if ( destpubkey33 != 0 )
787                 memcpy(destpubkey33,pindex->pubkey33,33);
788             return(pindex->notaryid);
789         }
790         komodo_index2pubkey33(pubkey33,pindex,height);
791         if ( destpubkey33 != 0 )
792             memcpy(destpubkey33,pindex->pubkey33,33);
793         if ( pindex->didinit != 0 )
794             return(pindex->notaryid);
795         timestamp = pindex->GetBlockTime();
796         if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 )
797         {
798             for (i=0; i<num; i++)
799                 if ( memcmp(pubkeys[i],pubkey33,33) == 0 )
800                     return(i);
801         }
802     }
803     fprintf(stderr,"komodo_minerid height.%d null pindex\n",height);
804     return(komodo_electednotary(&numnotaries,pubkey33,height,timestamp));
805 }*/
806
807 int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height)
808 {
809     int32_t i,j,n,duplicate; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33];
810     memset(mids,-1,sizeof(*mids)*66);
811     n = komodo_notaries(notarypubs33,height,0);
812     for (i=duplicate=0; i<66; i++)
813     {
814         if ( (pindex= komodo_chainactive(height-i)) != 0 )
815         {
816             blocktimes[i] = pindex->nTime;
817             if ( komodo_blockload(block,pindex) == 0 )
818             {
819                 komodo_block2pubkey33(pubkeys[i],&block);
820                 for (j=0; j<n; j++)
821                 {
822                     if ( memcmp(notarypubs33[j],pubkeys[i],33) == 0 )
823                     {
824                         mids[i] = j;
825                         (*nonzpkeysp)++;
826                         break;
827                     }
828                 }
829             } else fprintf(stderr,"couldnt load block.%d\n",height);
830             if ( mids[0] >= 0 && i > 0 && mids[i] == mids[0] )
831                 duplicate++;
832         }
833     }
834     if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) )
835         return(1);
836     else return(0);
837 }
838
839 int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) // deprecate
840 {
841     /*int32_t i,n=0;
842      for (i=0; i<width; i++,n++)
843      {
844      if ( height-i <= 0 )
845      break;
846      minerids[i] = komodo_minerid(height - i,0);
847      }
848      return(n);*/
849     fprintf(stderr,"komodo_minerids is deprecated\n");
850     return(-1);
851 }
852
853 int32_t komodo_is_special(uint8_t pubkeys[66][33],int32_t mids[66],uint32_t blocktimes[66],int32_t height,uint8_t pubkey33[33],uint32_t blocktime)
854 {
855     int32_t i,j,notaryid=0,minerid,limit,nid; uint8_t destpubkey33[33];
856     komodo_chosennotary(&notaryid,height,pubkey33,blocktimes[0]);
857     if ( height >= 82000 )
858     {
859         if ( notaryid >= 0 )
860         {
861             for (i=1; i<66; i++)
862             {
863                 if ( mids[i] == notaryid )
864                 {
865                     if ( height > 792000 )
866                     {
867                         for (j=0; j<66; j++)
868                             fprintf(stderr,"%d ",mids[j]);
869                         fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i);
870                         return(-1);
871                     } else break;
872                 }
873             }
874             if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 )
875             {
876                 //if ( height > 790000 )
877                 //    fprintf(stderr,"lag.%d ht.%d n.%d blocktimes[%u vs %u %u]\n",blocktime-blocktimes[1],height,notaryid,blocktime,blocktimes[0],blocktimes[1]);
878                 if ( height > 807000 )
879                     return(-2);
880             }
881             return(1);
882         } else return(0);
883     }
884     else
885     {
886         if ( height >= 34000 && notaryid >= 0 )
887         {
888             if ( height < 79693 )
889                 limit = 64;
890             else if ( height < 82000 )
891                 limit = 8;
892             else limit = 66;
893             for (i=1; i<limit; i++)
894             {
895                 komodo_chosennotary(&nid,height-i,pubkey33,blocktimes[i]);
896                 if ( nid == notaryid )
897                 {
898                     //for (j=0; j<66; j++)
899                     //    fprintf(stderr,"%d ",mids[j]);
900                     //fprintf(stderr,"ht.%d repeat mids[%d] nid.%d notaryid.%d\n",height-i,i,nid,notaryid);
901                     if ( height > 225000 )
902                         return(-1);
903                 }
904             }
905             //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit);
906             return(1);
907         }
908     }
909     return(0);
910 }
911
912 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)
913 {
914     int32_t depth,notarized_ht; uint256 MoM,kmdtxid;
915     depth = komodo_MoMdata(&notarized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip);
916     memset(MoMp,0,sizeof(*MoMp));
917     memset(kmdtxidp,0,sizeof(*kmdtxidp));
918     *notarized_heightp = 0;
919     if ( depth > 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht )
920     {
921         *MoMp = MoM;
922         *notarized_heightp = notarized_ht;
923         *kmdtxidp = kmdtxid;
924     }
925     return(depth);
926 }
927
928 int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
929 {
930     int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex;
931     if ( (pindex= chainActive.Tip()) == 0 )
932         return(-1);
933     notarized_height = komodo_notarizeddata(pindex->nHeight,&notarized_hash,&notarized_desttxid);
934     *notarized_heightp = notarized_height;
935     if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
936     {
937         //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
938         if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
939         {
940             if ( nHeight < notarized_height )
941             {
942                 //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
943                 return(-1);
944             }
945             else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
946             {
947                 fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
948                 return(-1);
949             }
950         } //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);
951     }
952     //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 )
953     //    fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight);
954     return(0);
955 }
956
957 uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n)
958 {
959     LOCK(cs_main);
960     CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex;
961     *txheighttimep = *txheightp = *tiptimep = 0;
962     *valuep = 0;
963     if ( !GetTransaction(hash,tx,hashBlock,true) )
964         return(0);
965     uint32_t locktime = 0;
966     if ( n < tx.vout.size() )
967     {
968         if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
969         {
970             *valuep = tx.vout[n].nValue;
971             *txheightp = pindex->nHeight;
972             *txheighttimep = pindex->nTime;
973             if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 )
974                 *tiptimep = (uint32_t)tipindex->nTime;
975             locktime = tx.nLockTime;
976             //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep);
977         }
978     }
979     return(locktime);
980 }
981
982 uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
983
984 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)
985 {
986     uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex;
987     if ( (pindex= chainActive[tipheight]) != 0 )
988         tiptime = (uint32_t)pindex->nTime;
989     else fprintf(stderr,"cant find height[%d]\n",tipheight);
990     if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 )
991     {
992         if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) )
993             return(komodo_interest(*txheightp,value,*locktimep,tiptime));
994         //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);
995         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);
996     }
997     return(0);
998 }
999
1000 int32_t komodo_isrealtime(int32_t *kmdheightp)
1001 {
1002     struct komodo_state *sp; CBlockIndex *pindex;
1003     if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 )
1004         *kmdheightp = sp->CURRENT_HEIGHT;
1005     else *kmdheightp = 0;
1006     if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() )
1007         return(1);
1008     else return(0);
1009 }
1010
1011 int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag)
1012 {
1013     uint32_t cmptime = nTime;
1014     if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
1015     {
1016         if ( txheight > 246748 )
1017         {
1018             if ( txheight < 247205 )
1019                 cmptime -= 16000;
1020             if ( (int64_t)tx.nLockTime < cmptime-3600 )
1021             {
1022                 if ( tx.nLockTime != 1477258935 || dispflag != 0 )
1023                 {
1024                     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);
1025                 }
1026                 return(-1);
1027             }
1028             if ( 0 && dispflag != 0 )
1029                 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);
1030         }
1031     }
1032     return(0);
1033 }
1034
This page took 0.075171 seconds and 2 git commands to generate.