]> Git Repo - VerusCoin.git/blame - src/komodo_bitcoind.h
Test
[VerusCoin.git] / src / komodo_bitcoind.h
CommitLineData
d019c447 1/******************************************************************************
37fed603 2 * Copyright © 2014-2017 The SuperNET Developers. *
d019c447 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
3eea72f2 16// komodo functions that interact with bitcoind C++
17
9b0e1808 18#ifdef _WIN32
9d365796 19#include <curl/curl.h>
20#include <curl/easy.h>
9b0e1808 21#else
22#include <curl/curl.h>
23#include <curl/easy.h>
24#endif
25
5416af1d 26#include "komodo_defs.h"
27
36c733e9 28//#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr))
77be6cd9 29
9b0e1808 30struct MemoryStruct { char *memory; size_t size; };
c2b50ce0 31struct 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
4ec67e74 39/************************************************************************
40 *
41 * Initialize the string handler so that it is thread safe
42 *
43 ************************************************************************/
44
45void 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}
c2b50ce0 56
4ec67e74 57/************************************************************************
58 *
59 * Use the "writer" to accumulate text until done
60 *
61 ************************************************************************/
62
63size_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}
c2b50ce0 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
93char *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
c2b50ce0 144char *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);
162try_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:");
9d365796 169
c2b50ce0 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);
4ec67e74 173 curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function
c2b50ce0 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 }
9d365796 198
c2b50ce0 199 databuf = (char *)malloc(256 + strlen(command) + strlen(params));
200 sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
05e307ec 201 //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
c2b50ce0 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 }
c59a3beb 227 else if ( numretries >= 1 )
c2b50ce0 228 {
bb7f7473 229 //printf("Maximum number of retries exceeded!\n");
c2b50ce0 230 free(s.ptr);
231 return(0);
232 }
32323ea1 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);
c2b50ce0 235 free(s.ptr);
236 sleep((1<<numretries));
237 goto try_again;
9d365796 238
c2b50ce0 239 }
240 else
241 {
242 if ( command != 0 && specialcase == 0 )
243 {
244 count++;
245 elapsedsum += (OS_milliseconds() - starttime);
32323ea1 246 if ( (count % 1000000) == 0)
c2b50ce0 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}
9b0e1808 270
271static 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;
b858fa74 275 mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1));
9b0e1808 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
05d3d5ff 287char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3)
9b0e1808 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
0ded57c8 334char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port)
9b0e1808 335{
4ac6cd92 336 //static void *cHandle;
a9132082 337 char url[512],*retstr=0,*retstr2=0,postdata[8192];
365378b5 338 if ( params == 0 || params[0] == 0 )
339 params = (char *)"[]";
9b0e1808 340 if ( strlen(params) < sizeof(postdata)-128 )
341 {
3c0f5d94 342 sprintf(url,(char *)"http://127.0.0.1:%u",port);
9b0e1808 343 sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
05e307ec 344 //printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS);
0ded57c8 345 retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params);
c2b50ce0 346 //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0);
9b0e1808 347 }
1ccb1cf0 348 return(retstr2);
9b0e1808 349}
350
0cb025c1 351int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp)
b000fa04 352{
0cb025c1 353 char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0;
b000fa04 354 params[0] = 0;
355 *kmdnotarized_heightp = 0;
0cb025c1 356 if ( strcmp(dest,"KMD") == 0 )
b000fa04 357 {
05e307ec 358 port = KMD_PORT;
0cb025c1 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 )
b000fa04 370 {
70d83934 371 //printf("(%s)\n",jsonstr);
b000fa04 372 if ( (json= cJSON_Parse(jsonstr)) != 0 )
373 {
978ca795 374 if ( (item= jobj(json,(char *)"result")) != 0 )
033f496d 375 {
033f496d 376 height = jint(item,(char *)"blocks");
57dd4ada 377 *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height;
033f496d 378 }
b000fa04 379 free_json(json);
380 }
381 free(jsonstr);
382 }
383 sprintf(params,"[\"%s\", 1]",txidstr);
0cb025c1 384 if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 )
b000fa04 385 {
70d83934 386 //printf("(%s)\n",jsonstr);
b000fa04 387 if ( (json= cJSON_Parse(jsonstr)) != 0 )
388 {
978ca795 389 if ( (item= jobj(json,(char *)"result")) != 0 )
033f496d 390 {
391 txid_confirmations = jint(item,(char *)"confirmations");
033f496d 392 if ( txid_confirmations > 0 && height > txid_confirmations )
393 txid_height = height - txid_confirmations;
19857195 394 else txid_height = height;
094b401e 395 //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height);
033f496d 396 }
b000fa04 397 free_json(json);
398 }
399 free(jsonstr);
400 }
43cc3df6 401 }
b000fa04 402 return(txid_height);
403}
404
20a5cb84 405int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH)
b55c2367 406{
407 int32_t i; uint256 hash; char params[256];
408 for (i=0; i<32; i++)
ebd18944 409 ((uint8_t *)&hash)[i] = script[2+i];
d56e5945 410 if ( hash == NOTARIZED_HASH )
411 return(0);
b556919a 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]);
20a5cb84 417 printf(" opreturn from [%s] ht.%d\n",ASSETCHAINS_SYMBOL,height);
b556919a 418 return(-1);
b55c2367 419}
420
421int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID)
422{
c3153900 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] = '[';
eee28662 425 params[1] = '"';
426 for (i=0; i<32; i++)
c3153900 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());
ed937645 430 if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 )
431 return(0);
05c1e522 432 if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
a0b9382c 433 printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT);
b55c2367 434 if ( strcmp(dest,"KMD") == 0 )
b148643e 435 {
436 if ( KMDUSERPASS[0] != 0 )
5201bb51 437 {
438 if ( ASSETCHAINS_SYMBOL[0] != 0 )
a0b9382c 439 {
05e307ec 440 jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT);
21abd4df 441//printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr);
a0b9382c 442 }
443 }//else jsonstr = _dex_getrawtransaction();
48d0e5df 444 else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok
b148643e 445 }
b55c2367 446 else if ( strcmp(dest,"BTC") == 0 )
b148643e 447 {
448 if ( BTCUSERPASS[0] != 0 )
48d0e5df 449 {
eee28662 450 //printf("BTCUSERPASS.(%s)\n",BTCUSERPASS);
b148643e 451 jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,8332);
48d0e5df 452 }
b148643e 453 //else jsonstr = _dex_getrawtransaction();
48d0e5df 454 else return(0);
b148643e 455 }
9674c671 456 else
457 {
458 printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest);
459 return(-1);
460 }
b55c2367 461 if ( jsonstr != 0 )
462 {
13b64fd6 463 if ( (json= cJSON_Parse(jsonstr)) != 0 )
b55c2367 464 {
fa73aa67 465 if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 )
b55c2367 466 {
467 vout = jitem(vouts,n-1);
34c68daa 468 if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
a0b9382c 469 printf("vout.(%s)\n",jprint(vout,0));
523a5dc7 470 if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 )
b55c2367 471 {
523a5dc7 472 if ( (hexstr= jstr(skey,(char *)"hex")) != 0 )
b55c2367 473 {
e35bc6fe 474 printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str());
b55c2367 475 len = strlen(hexstr) >> 1;
476 decode_hex(script,len,hexstr);
279fac91 477 if ( script[1] == 0x4c )
478 {
479 script++;
480 len--;
481 }
482 else if ( script[1] == 0x4d )
483 {
484 script += 2;
485 len -= 2;
486 }
20a5cb84 487 retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH);
b55c2367 488 }
489 }
490 }
491 free_json(txjson);
492 }
493 free(jsonstr);
494 }
495 return(retval);
496}
497
2934460c 498/*uint256 komodo_getblockhash(int32_t height)
23256cca 499{
dffceecf 500 uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32];
23256cca 501 memset(&hash,0,sizeof(hash));
502 sprintf(params,"[%d]",height);
34017212 503 if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_PORT)) != 0 )
23256cca 504 {
ccf895cf 505 if ( (result= cJSON_Parse(jsonstr)) != 0 )
506 {
25391719 507 if ( (hexstr= jstr(result,(char *)"result")) != 0 )
ccf895cf 508 {
509 if ( is_hexstr(hexstr,0) == 64 )
e9f49d50 510 {
511 decode_hex(revbuf,32,hexstr);
512 for (i=0; i<32; i++)
513 ((uint8_t *)&hash)[i] = revbuf[31-i];
514 }
ccf895cf 515 }
516 free_json(result);
517 }
5f1f19fd 518 printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash);
1fd57718 519 free(jsonstr);
23256cca 520 }
521 return(hash);
522}
523
2934460c 524uint256 _komodo_getblockhash(int32_t height);*/
6b0e06b5 525
23256cca 526uint64_t komodo_seed(int32_t height)
527{
39b462c7 528 uint64_t seed = 0;
2934460c 529 /*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds...
8aef9e40 530 {
39b462c7 531 uint256 hash,zero; CBlockIndex *pindex;
8aef9e40 532 memset(&hash,0,sizeof(hash));
533 memset(&zero,0,sizeof(zero));
534 if ( height > 10 )
535 height -= 10;
536 if ( ASSETCHAINS_SYMBOL[0] == 0 )
537 hash = _komodo_getblockhash(height);
538 if ( memcmp(&hash,&zero,sizeof(hash)) == 0 )
539 hash = komodo_getblockhash(height);
540 int32_t i;
541 for (i=0; i<32; i++)
542 printf("%02x",((uint8_t *)&hash)[i]);
543 printf(" seed.%d\n",height);
8c072b0b 544 seed = arith_uint256(hash.GetHex()).GetLow64();
8aef9e40 545 }
2934460c 546 else*/
8aef9e40 547 {
93fb251c 548 seed = (height << 13) ^ (height << 2);
549 seed <<= 21;
8aef9e40 550 seed |= (height & 0xffffffff);
93fb251c 551 seed ^= (seed << 17) ^ (seed << 1);
8aef9e40 552 }
23256cca 553 return(seed);
554}
555
3eea72f2 556uint32_t komodo_txtime(uint256 hash)
557{
558 CTransaction tx;
559 uint256 hashBlock;
7637aa7f 560 if (!GetTransaction(hash, tx,
561#ifndef KOMODO_ZCASH
562 Params().GetConsensus(),
563#endif
564 hashBlock, true))
3eea72f2 565 {
566 //printf("null GetTransaction\n");
567 return(tx.nLockTime);
568 }
569 return(0);
570}
571
572void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
573{
7c130297 574 char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
e0440cc3 575 //fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight);
c93dc546 576 komodo_init(pindex->nHeight);
f3a1de3a 577 if ( (sp= komodo_stateptr(symbol,dest)) != 0 )
7a183152 578 {
9c432d66 579 //sp->rewinding = pindex->nHeight;
580 //fprintf(stderr,"-%d ",pindex->nHeight);
7a183152 581 } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL);
3eea72f2 582}
583
303fbd20 584
f24b36ca 585int32_t komodo_is_notarytx(const CTransaction& tx)
586{
587 uint8_t *ptr,crypto777[33];
0554de3c 588 if ( tx.vout.size() > 0 )
589 {
f24b36ca 590#ifdef KOMODO_ZCASH
0554de3c 591 ptr = (uint8_t *)tx.vout[0].scriptPubKey.data();
f24b36ca 592#else
0554de3c 593 ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0];
f24b36ca 594#endif
0554de3c 595 if ( ptr != 0 )
303fbd20 596 {
0554de3c 597 decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR);
598 if ( memcmp(ptr+1,crypto777,33) == 0 )
599 {
600 //printf("found notarytx\n");
601 return(1);
602 }
303fbd20 603 }
f24b36ca 604 }
303fbd20 605 return(0);
f24b36ca 606}
607
3eea72f2 608int32_t komodo_block2height(CBlock *block)
609{
189d9dee 610 int32_t i,n,height = 0; uint8_t *ptr;
0554de3c 611 if ( block->vtx[0].vin.size() > 0 )
612 {
189d9dee 613#ifdef KOMODO_ZCASH
0554de3c 614 ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
189d9dee 615#else
0554de3c 616 ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
189d9dee 617#endif
0554de3c 618 if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 )
3eea72f2 619 {
0554de3c 620 //for (i=0; i<6; i++)
621 // printf("%02x",ptr[i]);
622 n = ptr[0];
623 for (i=0; i<n; i++)
624 {
625 //03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
626 height += ((uint32_t)ptr[i+1] << (i*8));
627 //printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
628 }
629 //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
3eea72f2 630 }
0554de3c 631 //komodo_init(height);
3eea72f2 632 }
633 return(height);
634}
635
636void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block)
637{
2dbf06e8 638 int32_t n;
0554de3c 639 memset(pubkey33,0,33);
97561034 640 if ( block.vtx[0].vout.size() > 0 )
0554de3c 641 {
da00f2dd 642#ifdef KOMODO_ZCASH
0554de3c 643 uint8_t *ptr = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data();
da00f2dd 644#else
0554de3c 645 uint8_t *ptr = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0];
da00f2dd 646#endif
0554de3c 647 //komodo_init(0);
648 n = block.vtx[0].vout[0].scriptPubKey.size();
649 if ( n == 35 )
650 memcpy(pubkey33,ptr+1,33);
651 }
3eea72f2 652}
653
d7093b33 654int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
875cf683 655{
656 block.SetNull();
657 // Open history file to read
658 CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION);
659 if (filein.IsNull())
660 return(-1);
661 // Read block
662 try { filein >> block; }
663 catch (const std::exception& e)
664 {
665 fprintf(stderr,"readblockfromdisk err B\n");
666 return(-1);
667 }
668 return(0);
669}
670
ae0bb3d3 671uint32_t komodo_chainactive_timestamp()
672{
673 if ( chainActive.Tip() != 0 )
674 return((uint32_t)chainActive.Tip()->GetBlockTime());
e34a9d43 675 else return(0);
ae0bb3d3 676}
677
7d44d3dd 678CBlockIndex *komodo_chainactive(int32_t height)
679{
5150cb47 680 if ( chainActive.Tip() != 0 )
7d44d3dd 681 {
5150cb47 682 if ( height <= chainActive.Tip()->nHeight )
683 return(chainActive[height]);
129d39b0 684 // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight);
d54aa57d 685 }
8c8a07ce 686 //fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height);
d54aa57d 687 return(0);
7d44d3dd 688}
689
690uint32_t komodo_heightstamp(int32_t height)
691{
0cb1d2da 692 CBlockIndex *ptr;
58bec1f9 693 if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 )
f21afd94 694 return(ptr->nTime);
0cb1d2da 695 else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height);
7d44d3dd 696 return(0);
697}
698
3eea72f2 699void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
700{
701 CBlock block;
bc9f2e03 702 //komodo_init(height);
3eea72f2 703 memset(pubkey33,0,33);
704 if ( pindex != 0 )
705 {
a92123ef 706 if ( komodo_blockload(block,pindex) == 0 )
707 komodo_block2pubkey33(pubkey33,block);
3eea72f2 708 }
709 else
710 {
711 // height -> pubkey33
712 //printf("extending chaintip komodo_index2pubkey33 height.%d need to get pubkey33\n",height);
713 }
714}
715
875cf683 716void komodo_connectpindex(CBlockIndex *pindex)
717{
718 CBlock block;
a92123ef 719 if ( komodo_blockload(block,pindex) == 0 )
720 komodo_connectblock(pindex,block);
875cf683 721}
722
85ef725a 723int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
8eaa7b03 724int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp);
6034c671 725
c142de7e 726int8_t komodo_minerid(int32_t height,uint8_t *pubkey33)
4a4e912b 727{
8eaa7b03 728 int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t _pubkey33[33],pubkeys[64][33];
a8e94add 729 if ( pubkey33 == 0 && (pindex= chainActive[height]) != 0 )
fc318ffe 730 {
85ef725a 731 timestamp = pindex->GetBlockTime();
c142de7e 732 if ( pubkey33 == 0 )
733 {
734 pubkey33 = _pubkey33;
735 komodo_index2pubkey33(pubkey33,pindex,height);
736 }
85ef725a 737 if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 )
e9ed4986 738 {
18594cf7 739 for (i=0; i<num; i++)
740 if ( memcmp(pubkeys[i],pubkey33,33) == 0 )
741 return(i);
fc318ffe 742 }
dac1ef88 743 }
8eaa7b03 744 return(komodo_electednotary(&numnotaries,pubkey33,height,timestamp));
4a4e912b 745}
746
8c654ec5 747int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,int32_t *nonzpkeysp,int32_t height)
353af8aa 748{
dac1ef88 749 int32_t i,j,duplicate; CBlockIndex *pindex; uint8_t pubkey33[33];
353af8aa 750 memset(mids,-1,sizeof(*mids)*66);
751 for (i=duplicate=0; i<66; i++)
752 {
3c525df1 753 if ( (pindex= komodo_chainactive(height-i)) != 0 )
353af8aa 754 {
755 komodo_index2pubkey33(pubkey33,pindex,height-i);
8c654ec5 756 for (j=0; j<33; j++)
757 pubkeys[i][j] = pubkey33[j];
17c303dd 758 if ( (mids[i]= komodo_minerid(height-i,pubkey33)) >= 0 )
759 {
611acf22 760 //mids[i] = *(int32_t *)pubkey33;
353af8aa 761 (*nonzpkeysp)++;
17c303dd 762 }
353af8aa 763 if ( mids[0] >= 0 && i > 0 && mids[i] == mids[0] )
764 duplicate++;
3c525df1 765 }
353af8aa 766 }
f2805ceb 767 if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) )
353af8aa 768 return(1);
769 else return(0);
770}
771
780c9ff1 772int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width)
dbaf1154 773{
774 int32_t i,n=0;
780c9ff1 775 for (i=0; i<width; i++,n++)
056447a6 776 {
777 if ( height-i <= 0 )
778 break;
c142de7e 779 minerids[i] = komodo_minerid(height - i,0);
056447a6 780 }
dbaf1154 781 return(n);
782}
783
8683bd8d 784int32_t komodo_is_special(int32_t height,uint8_t pubkey33[33],uint32_t timestamp)
4a4e912b 785{
dae6126c 786 int32_t i,notaryid=0,minerid,limit,nid; uint8_t _pubkey33[33];
787 if ( height >= 225000 )
8683bd8d 788 komodo_chosennotary(&notaryid,height,_pubkey33,timestamp);
4a4e912b 789 if ( height >= 34000 && notaryid >= 0 )
790 {
031b1129 791 if ( height < 79693 )
792 limit = 64;
793 else if ( height < 82000 )
3fe63a7d 794 limit = 8;
28bc6208 795 else limit = 66;
1b3ce02c 796 for (i=1; i<limit; i++)
4a4e912b 797 {
8683bd8d 798 komodo_chosennotary(&nid,height-i,_pubkey33,timestamp);
8c072c2d 799 if ( nid == notaryid ) //komodo_minerid(height-i,_pubkey33)
66e3c532 800 {
86ad1cb1 801 if ( (0) && notaryid > 0 )
dae6126c 802 fprintf(stderr,"ht.%d notaryid.%d already mined -i.%d nid.%d\n",height,notaryid,i,nid);
803 if ( height > 225000 )
804 return(-1);
66e3c532 805 }
4a4e912b 806 }
6a645f7b 807 //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit);
4a4e912b 808 return(1);
809 }
810 return(0);
811}
812
b62d7030 813int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
814{
d82623d2 815 int32_t notarized_height; uint256 notarized_hash,notarized_desttxid; CBlockIndex *notary; CBlockIndex *pindex;
816 if ( (pindex= chainActive.Tip()) == 0 )
817 return(-1);
818 notarized_height = komodo_notarizeddata(pindex->nHeight,&notarized_hash,&notarized_desttxid);
b62d7030 819 *notarized_heightp = notarized_height;
aba9ea3c 820 if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
b62d7030 821 {
d82623d2 822 //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
b62d7030 823 if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
824 {
825 if ( nHeight < notarized_height )
826 {
2c5af2cd 827 //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
b62d7030 828 return(-1);
829 }
830 else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
831 {
beb911ec 832 fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
b62d7030 833 return(-1);
834 }
beb911ec 835 } 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);
836 }
837 else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 )
d82623d2 838 fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight);
b62d7030 839 return(0);
840}
485e48ca 841
83da1e16 842uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n)
c1c95e36 843{
844 LOCK(cs_main);
845 CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex;
63c93b0c 846 *txheighttimep = *txheightp = *tiptimep = 0;
847 *valuep = 0;
c1c95e36 848 if ( !GetTransaction(hash,tx,hashBlock,true) )
849 return(0);
850 uint32_t locktime = 0;
851 if ( n < tx.vout.size() )
852 {
853 if ( (pindex= mapBlockIndex[hashBlock]) != 0 && (tipindex= chainActive.Tip()) != 0 )
854 {
855 *valuep = tx.vout[n].nValue;
856 *txheightp = pindex->nHeight;
83da1e16 857 *txheighttimep = pindex->nTime;
c1c95e36 858 *tiptimep = tipindex->nTime;
859 locktime = tx.nLockTime;
1f52f946 860 //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep);
c1c95e36 861 }
862 }
863 return(locktime);
864}
865
866uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
798f28c7 867uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue)
c1c95e36 868{
83da1e16 869 uint64_t value; uint32_t tiptime,txheighttimep;
870 if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 )
c1c95e36 871 {
798f28c7 872 if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) )
873 return(komodo_interest(*txheightp,value,*locktimep,tiptime));
c1c95e36 874 //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);
1c2f0c49 875 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);
876 }
c1c95e36 877 return(0);
878}
8a7f7063 879
880int32_t komodo_isrealtime(int32_t *kmdheightp)
881{
d82623d2 882 struct komodo_state *sp; CBlockIndex *pindex;
8a7c9241 883 if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 )
ffbc2f00 884 *kmdheightp = sp->CURRENT_HEIGHT;
885 else *kmdheightp = 0;
1b5b89ba 886 if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() )
8a7f7063 887 return(1);
888 else return(0);
889}
14aa6cc0 890
3bc88f14 891int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag)
14aa6cc0 892{
893 uint32_t cmptime = nTime;
894 if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
895 {
3d02f57b 896 if ( txheight > 246748 )
14aa6cc0 897 {
898 if ( txheight < 247205 )
39d28b06 899 cmptime -= 16000;
14aa6cc0 900 if ( (int64_t)tx.nLockTime < cmptime-3600 )
901 {
bbaa0f9d 902 if ( tx.nLockTime != 1477258935 || dispflag != 0 )
14aa6cc0 903 {
66294e69 904 //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);
14aa6cc0 905 }
906 return(-1);
907 }
948ad8f3 908 if ( 0 && dispflag != 0 )
3bc88f14 909 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);
14aa6cc0 910 }
14aa6cc0 911 }
912 return(0);
913}
This page took 0.358275 seconds and 4 git commands to generate.