]> Git Repo - VerusCoin.git/blame - src/komodo_bitcoind.h
relax absurd fee threshold
[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
19#include <curl.h>
20#include <easy.h>
21#else
22#include <curl/curl.h>
23#include <curl/easy.h>
24#endif
25
fba6038c 26#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr))
77be6cd9 27
9b0e1808 28struct MemoryStruct { char *memory; size_t size; };
c2b50ce0 29struct return_string { char *ptr; size_t len; };
30
31// return data from the server
32#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
33#define CURL_GLOBAL_SSL (1<<0)
34#define CURL_GLOBAL_WIN32 (1<<1)
35
36
4ec67e74 37/************************************************************************
38 *
39 * Initialize the string handler so that it is thread safe
40 *
41 ************************************************************************/
42
43void init_string(struct return_string *s)
44{
45 s->len = 0;
46 s->ptr = (char *)calloc(1,s->len+1);
47 if ( s->ptr == NULL )
48 {
49 fprintf(stderr,"init_string malloc() failed\n");
50 exit(-1);
51 }
52 s->ptr[0] = '\0';
53}
c2b50ce0 54
4ec67e74 55/************************************************************************
56 *
57 * Use the "writer" to accumulate text until done
58 *
59 ************************************************************************/
60
61size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s)
62{
63 size_t new_len = s->len + size*nmemb;
64 s->ptr = (char *)realloc(s->ptr,new_len+1);
65 if ( s->ptr == NULL )
66 {
67 fprintf(stderr, "accumulate realloc() failed\n");
68 exit(-1);
69 }
70 memcpy(s->ptr+s->len,ptr,size*nmemb);
71 s->ptr[new_len] = '\0';
72 s->len = new_len;
73 return(size * nmemb);
74}
c2b50ce0 75
76/************************************************************************
77 *
78 * return the current system time in milliseconds
79 *
80 ************************************************************************/
81
82#define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field
83#ifdef EXTRACT_BITCOIND_RESULT
84
85/************************************************************************
86 *
87 * perform post processing of the results
88 *
89 ************************************************************************/
90
91char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params)
92{
93 long i,j,len; char *retstr = 0; cJSON *json,*result,*error;
94 //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
95 if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
96 {
97 if ( strcmp(command,"signrawtransaction") != 0 )
98 printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
99 return(rpcstr);
100 }
101 json = cJSON_Parse(rpcstr);
102 if ( json == 0 )
103 {
104 printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params);
105 free(rpcstr);
106 return(0);
107 }
108 result = cJSON_GetObjectItem(json,"result");
109 error = cJSON_GetObjectItem(json,"error");
110 if ( error != 0 && result != 0 )
111 {
112 if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL )
113 {
114 retstr = cJSON_Print(result);
115 len = strlen(retstr);
116 if ( retstr[0] == '"' && retstr[len-1] == '"' )
117 {
118 for (i=1,j=0; i<len-1; i++,j++)
119 retstr[j] = retstr[i];
120 retstr[j] = 0;
121 }
122 }
123 else if ( (error->type&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL )
124 {
125 if ( strcmp(command,"signrawtransaction") != 0 )
126 printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr);
127 }
128 free(rpcstr);
129 } else retstr = rpcstr;
130 free_json(json);
131 //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
132 return(retstr);
133}
134#endif
135
136/************************************************************************
137 *
138 * perform the query
139 *
140 ************************************************************************/
141
c2b50ce0 142char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params)
143{
144 static int didinit,count,count2; static double elapsedsum,elapsedsum2;
145 struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle;
146 char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
147 if ( didinit == 0 )
148 {
149 didinit = 1;
150 curl_global_init(CURL_GLOBAL_ALL); //init the curl session
151 }
152 numretries = 0;
153 if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 )
154 specialcase = 1;
155 else specialcase = 0;
156 if ( url[0] == 0 )
157 strcpy(url,"http://127.0.0.1:7876/nxt");
158 if ( specialcase != 0 && 0 )
159 printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params);
160try_again:
161 if ( retstrp != 0 )
162 *retstrp = 0;
163 starttime = OS_milliseconds();
164 curl_handle = curl_easy_init();
165 init_string(&s);
166 headers = curl_slist_append(0,"Expect:");
167
168 curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
169 curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
170 curl_easy_setopt(curl_handle,CURLOPT_URL, url);
4ec67e74 171 curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function
c2b50ce0 172 curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
173 curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
174 curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
175 if ( strncmp(url,"https",5) == 0 )
176 {
177 curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
178 curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
179 }
180 if ( userpass != 0 )
181 curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass);
182 databuf = 0;
183 if ( params != 0 )
184 {
185 if ( command != 0 && specialcase == 0 )
186 {
187 len = strlen(params);
188 if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) {
189 bracket0 = bracket1 = (char *)"";
190 }
191 else
192 {
193 bracket0 = (char *)"[";
194 bracket1 = (char *)"]";
195 }
196
197 databuf = (char *)malloc(256 + strlen(command) + strlen(params));
198 sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
199 //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
200 //
201 } //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
202 curl_easy_setopt(curl_handle,CURLOPT_POST,1L);
203 if ( databuf != 0 )
204 curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf);
205 else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params);
206 }
207 //laststart = milliseconds();
208 res = curl_easy_perform(curl_handle);
209 curl_slist_free_all(headers);
210 curl_easy_cleanup(curl_handle);
211 if ( databuf != 0 ) // clean up temporary buffer
212 {
213 free(databuf);
214 databuf = 0;
215 }
216 if ( res != CURLE_OK )
217 {
218 numretries++;
219 if ( specialcase != 0 )
220 {
221 printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
222 free(s.ptr);
223 return(0);
224 }
c59a3beb 225 else if ( numretries >= 1 )
c2b50ce0 226 {
bb7f7473 227 //printf("Maximum number of retries exceeded!\n");
c2b50ce0 228 free(s.ptr);
229 return(0);
230 }
32323ea1 231 if ( (rand() % 1000) == 0 )
232 printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
c2b50ce0 233 free(s.ptr);
234 sleep((1<<numretries));
235 goto try_again;
236
237 }
238 else
239 {
240 if ( command != 0 && specialcase == 0 )
241 {
242 count++;
243 elapsedsum += (OS_milliseconds() - starttime);
32323ea1 244 if ( (count % 1000000) == 0)
c2b50ce0 245 printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
246 if ( retstrp != 0 )
247 {
248 *retstrp = s.ptr;
249 return(s.ptr);
250 }
251 return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params));
252 }
253 else
254 {
255 if ( 0 && specialcase != 0 )
256 fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr);
257 count2++;
258 elapsedsum2 += (OS_milliseconds() - starttime);
259 if ( (count2 % 10000) == 0)
260 printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command);
261 return(s.ptr);
262 }
263 }
264 printf("bitcoind_RPC: impossible case\n");
265 free(s.ptr);
266 return(0);
267}
9b0e1808 268
269static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data)
270{
271 size_t realsize = (size * nmemb);
272 struct MemoryStruct *mem = (struct MemoryStruct *)data;
b858fa74 273 mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1));
9b0e1808 274 if ( mem->memory != 0 )
275 {
276 if ( ptr != 0 )
277 memcpy(&(mem->memory[mem->size]),ptr,realsize);
278 mem->size += realsize;
279 mem->memory[mem->size] = 0;
280 }
281 //printf("got %d bytes\n",(int32_t)(size*nmemb));
282 return(realsize);
283}
284
05d3d5ff 285char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3)
9b0e1808 286{
287 struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0;
288 if ( (cHandle= *cHandlep) == NULL )
289 *cHandlep = cHandle = curl_easy_init();
290 else curl_easy_reset(cHandle);
291 //#ifdef DEBUG
292 //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1);
293 //#endif
294 curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
295 curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0);
296 //curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1);
297 curl_easy_setopt(cHandle,CURLOPT_URL,url);
298 curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10);
299 if ( userpass != 0 && userpass[0] != 0 )
300 curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass);
301 if ( postfields != 0 && postfields[0] != 0 )
302 {
303 curl_easy_setopt(cHandle,CURLOPT_POST,1);
304 curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields);
305 }
306 if ( hdr0 != NULL && hdr0[0] != 0 )
307 {
308 //printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:"");
309 headers = curl_slist_append(headers,hdr0);
310 if ( hdr1 != 0 && hdr1[0] != 0 )
311 headers = curl_slist_append(headers,hdr1);
312 if ( hdr2 != 0 && hdr2[0] != 0 )
313 headers = curl_slist_append(headers,hdr2);
314 if ( hdr3 != 0 && hdr3[0] != 0 )
315 headers = curl_slist_append(headers,hdr3);
316 } //headers = curl_slist_append(0,"Expect:");
317 if ( headers != 0 )
318 curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers);
319 //res = curl_easy_perform(cHandle);
320 memset(&chunk,0,sizeof(chunk));
321 curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback);
322 curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk);
323 curl_easy_perform(cHandle);
324 curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code);
325 if ( headers != 0 )
326 curl_slist_free_all(headers);
327 if ( code != 200 )
328 printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory);
329 return(chunk.memory);
330}
331
0ded57c8 332char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port)
9b0e1808 333{
4ac6cd92 334 //static void *cHandle;
a9132082 335 char url[512],*retstr=0,*retstr2=0,postdata[8192];
365378b5 336 if ( params == 0 || params[0] == 0 )
337 params = (char *)"[]";
9b0e1808 338 if ( strlen(params) < sizeof(postdata)-128 )
339 {
3c0f5d94 340 sprintf(url,(char *)"http://127.0.0.1:%u",port);
9b0e1808 341 sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
f38345e9 342 //printf("postdata.(%s) USERPASS.(%s)\n",postdata,KMDUSERPASS);
0ded57c8 343 retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params);
c2b50ce0 344 //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0);
9b0e1808 345 }
1ccb1cf0 346 return(retstr2);
9b0e1808 347}
348
20a5cb84 349int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH)
b55c2367 350{
351 int32_t i; uint256 hash; char params[256];
352 for (i=0; i<32; i++)
ebd18944 353 ((uint8_t *)&hash)[i] = script[2+i];
d56e5945 354 if ( hash == NOTARIZED_HASH )
355 return(0);
b556919a 356 for (i=0; i<32; i++)
357 printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]);
358 printf(" notarized, ");
359 for (i=0; i<32; i++)
360 printf("%02x",((uint8_t *)&hash)[i]);
20a5cb84 361 printf(" opreturn from [%s] ht.%d\n",ASSETCHAINS_SYMBOL,height);
b556919a 362 return(-1);
b55c2367 363}
364
365int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID)
366{
c3153900 367 char params[256],*jsonstr,*hexstr; uint8_t script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey;
368 /*params[0] = '[';
eee28662 369 params[1] = '"';
370 for (i=0; i<32; i++)
c3153900 371 sprintf(&params[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]);
372 strcat(params,"\", 1]");*/
373 sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str());
ed937645 374 if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 )
375 return(0);
a82f9da1 376 //printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT);
b55c2367 377 if ( strcmp(dest,"KMD") == 0 )
b148643e 378 {
379 if ( KMDUSERPASS[0] != 0 )
380 jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,7771);
381 //else jsonstr = _dex_getrawtransaction();
48d0e5df 382 else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok
b148643e 383 }
b55c2367 384 else if ( strcmp(dest,"BTC") == 0 )
b148643e 385 {
386 if ( BTCUSERPASS[0] != 0 )
48d0e5df 387 {
eee28662 388 //printf("BTCUSERPASS.(%s)\n",BTCUSERPASS);
b148643e 389 jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,8332);
48d0e5df 390 }
b148643e 391 //else jsonstr = _dex_getrawtransaction();
48d0e5df 392 else return(0);
b148643e 393 }
9674c671 394 else
395 {
396 printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest);
397 return(-1);
398 }
b55c2367 399 if ( jsonstr != 0 )
400 {
13b64fd6 401 if ( (json= cJSON_Parse(jsonstr)) != 0 )
b55c2367 402 {
fa73aa67 403 if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 )
b55c2367 404 {
405 vout = jitem(vouts,n-1);
51ecd3f9 406 //printf("vout.(%s)\n",jprint(vout,0));
523a5dc7 407 if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 )
b55c2367 408 {
523a5dc7 409 if ( (hexstr= jstr(skey,(char *)"hex")) != 0 )
b55c2367 410 {
ebd18944 411 //printf("HEX.(%s)\n",hexstr);
b55c2367 412 len = strlen(hexstr) >> 1;
413 decode_hex(script,len,hexstr);
20a5cb84 414 retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH);
b55c2367 415 }
416 }
417 }
418 free_json(txjson);
419 }
420 free(jsonstr);
421 }
422 return(retval);
423}
424
23256cca 425uint256 komodo_getblockhash(int32_t height)
426{
dffceecf 427 uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32];
23256cca 428 memset(&hash,0,sizeof(hash));
429 sprintf(params,"[%d]",height);
ccf895cf 430 if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,7771)) != 0 )
23256cca 431 {
ccf895cf 432 if ( (result= cJSON_Parse(jsonstr)) != 0 )
433 {
25391719 434 if ( (hexstr= jstr(result,(char *)"result")) != 0 )
ccf895cf 435 {
436 if ( is_hexstr(hexstr,0) == 64 )
e9f49d50 437 {
438 decode_hex(revbuf,32,hexstr);
439 for (i=0; i<32; i++)
440 ((uint8_t *)&hash)[i] = revbuf[31-i];
441 }
ccf895cf 442 }
443 free_json(result);
444 }
5f1f19fd 445 printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash);
1fd57718 446 free(jsonstr);
23256cca 447 }
448 return(hash);
449}
450
6b0e06b5 451uint256 _komodo_getblockhash(int32_t height);
452
23256cca 453uint64_t komodo_seed(int32_t height)
454{
39b462c7 455 uint64_t seed = 0;
8aef9e40 456 if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds...
457 {
39b462c7 458 uint256 hash,zero; CBlockIndex *pindex;
8aef9e40 459 memset(&hash,0,sizeof(hash));
460 memset(&zero,0,sizeof(zero));
461 if ( height > 10 )
462 height -= 10;
463 if ( ASSETCHAINS_SYMBOL[0] == 0 )
464 hash = _komodo_getblockhash(height);
465 if ( memcmp(&hash,&zero,sizeof(hash)) == 0 )
466 hash = komodo_getblockhash(height);
467 int32_t i;
468 for (i=0; i<32; i++)
469 printf("%02x",((uint8_t *)&hash)[i]);
470 printf(" seed.%d\n",height);
8c072b0b 471 seed = arith_uint256(hash.GetHex()).GetLow64();
8aef9e40 472 }
473 else
474 {
93fb251c 475 seed = (height << 13) ^ (height << 2);
476 seed <<= 21;
8aef9e40 477 seed |= (height & 0xffffffff);
93fb251c 478 seed ^= (seed << 17) ^ (seed << 1);
8aef9e40 479 }
23256cca 480 return(seed);
481}
482
3eea72f2 483uint32_t komodo_txtime(uint256 hash)
484{
485 CTransaction tx;
486 uint256 hashBlock;
7637aa7f 487 if (!GetTransaction(hash, tx,
488#ifndef KOMODO_ZCASH
489 Params().GetConsensus(),
490#endif
491 hashBlock, true))
3eea72f2 492 {
493 //printf("null GetTransaction\n");
494 return(tx.nLockTime);
495 }
496 return(0);
497}
498
499void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
500{
b46eae72 501 char symbol[16],dest[16]; struct komodo_state *sp;
c93dc546 502 komodo_init(pindex->nHeight);
f3a1de3a 503 if ( (sp= komodo_stateptr(symbol,dest)) != 0 )
7a183152 504 {
9c432d66 505 //sp->rewinding = pindex->nHeight;
506 //fprintf(stderr,"-%d ",pindex->nHeight);
7a183152 507 } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL);
3eea72f2 508}
509
f24b36ca 510int32_t komodo_is_notarytx(const CTransaction& tx)
511{
512 uint8_t *ptr,crypto777[33];
513#ifdef KOMODO_ZCASH
ed652d8b 514 ptr = (uint8_t *)tx.vout[0].scriptPubKey.data();
f24b36ca 515#else
ed652d8b 516 ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0];
f24b36ca 517#endif
518 decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR);
519 if ( memcmp(ptr+1,crypto777,33) == 0 )
520 {
0e2acef5 521 //printf("found notarytx\n");
f24b36ca 522 return(1);
523 }
524 else return(0);
525}
526
3eea72f2 527int32_t komodo_block2height(CBlock *block)
528{
189d9dee 529 int32_t i,n,height = 0; uint8_t *ptr;
189d9dee 530#ifdef KOMODO_ZCASH
531 ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
532#else
533 ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
534#endif
3eea72f2 535 if ( block->vtx[0].vin[0].scriptSig.size() > 5 )
536 {
537 //for (i=0; i<6; i++)
538 // printf("%02x",ptr[i]);
539 n = ptr[0];
540 for (i=0; i<n; i++)
541 {
542 //03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
543 height += ((uint32_t)ptr[i+1] << (i*8));
544 //printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
545 }
546 //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
547 }
bc9f2e03 548 //komodo_init(height);
3eea72f2 549 return(height);
550}
551
552void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block)
553{
2dbf06e8 554 int32_t n;
da00f2dd 555#ifdef KOMODO_ZCASH
484f8777 556 uint8_t *ptr = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data();
da00f2dd 557#else
558 uint8_t *ptr = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0];
559#endif
bc9f2e03 560 //komodo_init(0);
18594cf7 561 n = block.vtx[0].vout[0].scriptPubKey.size();
562 if ( n == 35 )
563 memcpy(pubkey33,ptr+1,33);
564 else memset(pubkey33,0,33);
3eea72f2 565}
566
d7093b33 567int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
875cf683 568{
569 block.SetNull();
570 // Open history file to read
571 CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION);
572 if (filein.IsNull())
573 return(-1);
574 // Read block
575 try { filein >> block; }
576 catch (const std::exception& e)
577 {
578 fprintf(stderr,"readblockfromdisk err B\n");
579 return(-1);
580 }
581 return(0);
582}
583
3eea72f2 584void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
585{
586 CBlock block;
bc9f2e03 587 //komodo_init(height);
3eea72f2 588 memset(pubkey33,0,33);
589 if ( pindex != 0 )
590 {
a92123ef 591 if ( komodo_blockload(block,pindex) == 0 )
592 komodo_block2pubkey33(pubkey33,block);
3eea72f2 593 }
594 else
595 {
596 // height -> pubkey33
597 //printf("extending chaintip komodo_index2pubkey33 height.%d need to get pubkey33\n",height);
598 }
599}
600
875cf683 601void komodo_connectpindex(CBlockIndex *pindex)
602{
603 CBlock block;
a92123ef 604 if ( komodo_blockload(block,pindex) == 0 )
605 komodo_connectblock(pindex,block);
875cf683 606}
607
6034c671 608int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height);
609
4a4e912b 610int8_t komodo_minerid(int32_t height)
611{
18594cf7 612 int32_t num,i; CBlockIndex *pindex; uint8_t pubkey33[33],pubkeys[64][33];
fc318ffe 613 if ( (pindex= chainActive[height]) != 0 )
614 {
18594cf7 615 komodo_index2pubkey33(pubkey33,pindex,height);
616 if ( (num= komodo_notaries(pubkeys,height)) > 0 )
e9ed4986 617 {
18594cf7 618 for (i=0; i<num; i++)
619 if ( memcmp(pubkeys[i],pubkey33,33) == 0 )
620 return(i);
fc318ffe 621 }
622 }
623 return(-1);
4a4e912b 624}
625
dbaf1154 626int32_t komodo_minerids(uint8_t *minerids,int32_t height)
627{
628 int32_t i,n=0;
629 for (i=0; i<1000; i++,n++)
056447a6 630 {
631 if ( height-i <= 0 )
632 break;
dbaf1154 633 minerids[i] = komodo_minerid(height - i);
056447a6 634 }
dbaf1154 635 return(n);
636}
637
4a4e912b 638int32_t komodo_is_special(int32_t height,uint8_t pubkey33[33])
639{
28bc6208 640 int32_t i,notaryid,minerid,limit;
4a4e912b 641 komodo_chosennotary(&notaryid,height,pubkey33);
642 if ( height >= 34000 && notaryid >= 0 )
643 {
031b1129 644 if ( height < 79693 )
645 limit = 64;
646 else if ( height < 82000 )
3fe63a7d 647 limit = 8;
28bc6208 648 else limit = 66;
1b3ce02c 649 for (i=1; i<limit; i++)
4a4e912b 650 {
e21ffa1d 651 if ( komodo_minerid(height-i) == notaryid )
66e3c532 652 {
6a645f7b 653 //fprintf(stderr,"ht.%d notaryid.%d already mined -i.%d\n",height,notaryid,i);
4a4e912b 654 return(-1);
66e3c532 655 }
4a4e912b 656 }
6a645f7b 657 //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit);
4a4e912b 658 return(1);
659 }
660 return(0);
661}
662
b62d7030 663int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
664{
d82623d2 665 int32_t notarized_height; uint256 notarized_hash,notarized_desttxid; CBlockIndex *notary; CBlockIndex *pindex;
666 if ( (pindex= chainActive.Tip()) == 0 )
667 return(-1);
668 notarized_height = komodo_notarizeddata(pindex->nHeight,&notarized_hash,&notarized_desttxid);
b62d7030 669 *notarized_heightp = notarized_height;
aba9ea3c 670 if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
b62d7030 671 {
d82623d2 672 //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
b62d7030 673 if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
674 {
675 if ( nHeight < notarized_height )
676 {
677 fprintf(stderr,"nHeight.%d < NOTARIZED_HEIGHT.%d\n",nHeight,notarized_height);
678 return(-1);
679 }
680 else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
681 {
682 fprintf(stderr,"nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",nHeight,notarized_height);
683 return(-1);
684 }
685 } else fprintf(stderr,"unexpected error notary_hash %s ht.%d at ht.%d\n",notarized_hash.ToString().c_str(),notarized_height,notary->nHeight);
e0086592 686 } else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 )
d82623d2 687 fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight);
b62d7030 688 return(0);
689}
485e48ca 690
c1c95e36 691uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n)
692{
693 LOCK(cs_main);
694 CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex;
695 if ( !GetTransaction(hash,tx,hashBlock,true) )
696 return(0);
697 uint32_t locktime = 0;
698 if ( n < tx.vout.size() )
699 {
700 if ( (pindex= mapBlockIndex[hashBlock]) != 0 && (tipindex= chainActive.Tip()) != 0 )
701 {
702 *valuep = tx.vout[n].nValue;
703 *txheightp = pindex->nHeight;
704 *tiptimep = tipindex->nTime;
705 locktime = tx.nLockTime;
1f52f946 706 //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep);
c1c95e36 707 }
708 }
709 return(locktime);
710}
711
712uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
798f28c7 713uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue)
c1c95e36 714{
798f28c7 715 uint64_t value; uint32_t tiptime;
716 if ( (*locktimep= komodo_interest_args(txheightp,&tiptime,&value,hash,n)) != 0 )
c1c95e36 717 {
798f28c7 718 if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) )
719 return(komodo_interest(*txheightp,value,*locktimep,tiptime));
c1c95e36 720 //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 721 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);
722 }
c1c95e36 723 return(0);
724}
8a7f7063 725
726int32_t komodo_isrealtime(int32_t *kmdheightp)
727{
d82623d2 728 struct komodo_state *sp; CBlockIndex *pindex;
8a7c9241 729 if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 )
ffbc2f00 730 *kmdheightp = sp->CURRENT_HEIGHT;
731 else *kmdheightp = 0;
d82623d2 732 if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight == (int32_t)komodo_longestchain() )
8a7f7063 733 return(1);
734 else return(0);
735}
This page took 0.246011 seconds and 4 git commands to generate.