]> Git Repo - VerusCoin.git/blame - src/komodo_bitcoind.h
Test
[VerusCoin.git] / src / komodo_bitcoind.h
CommitLineData
d019c447 1/******************************************************************************
713c2a94 2 * Copyright © 2014-2018 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
c615ffff 28int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
29int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp);
30
36c733e9 31//#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr))
77be6cd9 32
9b0e1808 33struct MemoryStruct { char *memory; size_t size; };
c2b50ce0 34struct 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
4ec67e74 42/************************************************************************
43 *
44 * Initialize the string handler so that it is thread safe
45 *
46 ************************************************************************/
47
48void 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}
c2b50ce0 59
4ec67e74 60/************************************************************************
61 *
62 * Use the "writer" to accumulate text until done
63 *
64 ************************************************************************/
65
66size_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}
c2b50ce0 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
96char *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
c2b50ce0 147char *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);
165try_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:");
f796b1fb 172
173 curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
c2b50ce0 174 curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
175 curl_easy_setopt(curl_handle,CURLOPT_URL, url);
4ec67e74 176 curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function
c2b50ce0 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
f796b1fb 179 curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
c2b50ce0 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 }
f796b1fb 201
c2b50ce0 202 databuf = (char *)malloc(256 + strlen(command) + strlen(params));
203 sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
05e307ec 204 //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
c2b50ce0 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 }
c59a3beb 230 else if ( numretries >= 1 )
c2b50ce0 231 {
bb7f7473 232 //printf("Maximum number of retries exceeded!\n");
c2b50ce0 233 free(s.ptr);
234 return(0);
235 }
32323ea1 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);
c2b50ce0 238 free(s.ptr);
239 sleep((1<<numretries));
240 goto try_again;
f796b1fb 241
c2b50ce0 242 }
243 else
244 {
245 if ( command != 0 && specialcase == 0 )
246 {
247 count++;
248 elapsedsum += (OS_milliseconds() - starttime);
32323ea1 249 if ( (count % 1000000) == 0)
c2b50ce0 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}
9b0e1808 273
274static 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;
b858fa74 278 mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1));
9b0e1808 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
05d3d5ff 290char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3)
9b0e1808 291{
292 struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0;
293 if ( (cHandle= *cHandlep) == NULL )
f796b1fb 294 *cHandlep = cHandle = curl_easy_init();
9b0e1808 295 else curl_easy_reset(cHandle);
296 //#ifdef DEBUG
f796b1fb 297 //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1);
9b0e1808 298 //#endif
f796b1fb 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);
9b0e1808 304 if ( userpass != 0 && userpass[0] != 0 )
305 curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass);
f796b1fb 306 if ( postfields != 0 && postfields[0] != 0 )
9b0e1808 307 {
308 curl_easy_setopt(cHandle,CURLOPT_POST,1);
f796b1fb 309 curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields);
9b0e1808 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
0ded57c8 337char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port)
9b0e1808 338{
50653d13 339 //static void *cHandle;
a9132082 340 char url[512],*retstr=0,*retstr2=0,postdata[8192];
365378b5 341 if ( params == 0 || params[0] == 0 )
342 params = (char *)"[]";
9b0e1808 343 if ( strlen(params) < sizeof(postdata)-128 )
344 {
3c0f5d94 345 sprintf(url,(char *)"http://127.0.0.1:%u",port);
9b0e1808 346 sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
50653d13 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);
9b0e1808 350 }
1ccb1cf0 351 return(retstr2);
9b0e1808 352}
353
0cb025c1 354int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp)
b000fa04 355{
0cb025c1 356 char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0;
b000fa04 357 params[0] = 0;
358 *kmdnotarized_heightp = 0;
0cb025c1 359 if ( strcmp(dest,"KMD") == 0 )
b000fa04 360 {
05e307ec 361 port = KMD_PORT;
0cb025c1 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 )
b000fa04 373 {
70d83934 374 //printf("(%s)\n",jsonstr);
b000fa04 375 if ( (json= cJSON_Parse(jsonstr)) != 0 )
376 {
978ca795 377 if ( (item= jobj(json,(char *)"result")) != 0 )
033f496d 378 {
033f496d 379 height = jint(item,(char *)"blocks");
57dd4ada 380 *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height;
033f496d 381 }
b000fa04 382 free_json(json);
383 }
384 free(jsonstr);
385 }
386 sprintf(params,"[\"%s\", 1]",txidstr);
0cb025c1 387 if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 )
b000fa04 388 {
70d83934 389 //printf("(%s)\n",jsonstr);
b000fa04 390 if ( (json= cJSON_Parse(jsonstr)) != 0 )
391 {
978ca795 392 if ( (item= jobj(json,(char *)"result")) != 0 )
033f496d 393 {
394 txid_confirmations = jint(item,(char *)"confirmations");
033f496d 395 if ( txid_confirmations > 0 && height > txid_confirmations )
396 txid_height = height - txid_confirmations;
19857195 397 else txid_height = height;
094b401e 398 //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height);
033f496d 399 }
b000fa04 400 free_json(json);
401 }
402 free(jsonstr);
403 }
43cc3df6 404 }
b000fa04 405 return(txid_height);
406}
407
20a5cb84 408int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH)
b55c2367 409{
410 int32_t i; uint256 hash; char params[256];
411 for (i=0; i<32; i++)
ebd18944 412 ((uint8_t *)&hash)[i] = script[2+i];
d56e5945 413 if ( hash == NOTARIZED_HASH )
3e9fcad0 414 return(1);
b556919a 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]);
895977bf 420 printf(" opreturn from [%s] ht.%d MISMATCHED\n",ASSETCHAINS_SYMBOL,height);
b556919a 421 return(-1);
b55c2367 422}
423
424int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID)
425{
3da303b5 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;
c3153900 428 /*params[0] = '[';
f796b1fb 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]");*/
c3153900 433 sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str());
ed937645 434 if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 )
435 return(0);
05c1e522 436 if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
a0b9382c 437 printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT);
b55c2367 438 if ( strcmp(dest,"KMD") == 0 )
b148643e 439 {
440 if ( KMDUSERPASS[0] != 0 )
5201bb51 441 {
442 if ( ASSETCHAINS_SYMBOL[0] != 0 )
a0b9382c 443 {
05e307ec 444 jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT);
f796b1fb 445 //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr);
a0b9382c 446 }
447 }//else jsonstr = _dex_getrawtransaction();
48d0e5df 448 else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok
b148643e 449 }
b55c2367 450 else if ( strcmp(dest,"BTC") == 0 )
b148643e 451 {
452 if ( BTCUSERPASS[0] != 0 )
48d0e5df 453 {
eee28662 454 //printf("BTCUSERPASS.(%s)\n",BTCUSERPASS);
b148643e 455 jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,8332);
48d0e5df 456 }
b148643e 457 //else jsonstr = _dex_getrawtransaction();
48d0e5df 458 else return(0);
b148643e 459 }
9674c671 460 else
461 {
462 printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest);
463 return(-1);
464 }
b55c2367 465 if ( jsonstr != 0 )
466 {
13b64fd6 467 if ( (json= cJSON_Parse(jsonstr)) != 0 )
b55c2367 468 {
fa73aa67 469 if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 )
b55c2367 470 {
471 vout = jitem(vouts,n-1);
34c68daa 472 if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
a0b9382c 473 printf("vout.(%s)\n",jprint(vout,0));
523a5dc7 474 if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 )
b55c2367 475 {
523a5dc7 476 if ( (hexstr= jstr(skey,(char *)"hex")) != 0 )
b55c2367 477 {
895977bf 478 //printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str());
b55c2367 479 len = strlen(hexstr) >> 1;
480 decode_hex(script,len,hexstr);
279fac91 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 }
20a5cb84 491 retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH);
b55c2367 492 }
493 }
494 }
495 free_json(txjson);
496 }
497 free(jsonstr);
498 }
499 return(retval);
500}
501
2934460c 502/*uint256 komodo_getblockhash(int32_t height)
f796b1fb 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);
05c2ba63 507 if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_RPCPORT)) != 0 )
f796b1fb 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);*/
6b0e06b5 529
23256cca 530uint64_t komodo_seed(int32_t height)
531{
39b462c7 532 uint64_t seed = 0;
2934460c 533 /*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds...
f796b1fb 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*/
8aef9e40 551 {
93fb251c 552 seed = (height << 13) ^ (height << 2);
553 seed <<= 21;
8aef9e40 554 seed |= (height & 0xffffffff);
93fb251c 555 seed ^= (seed << 17) ^ (seed << 1);
8aef9e40 556 }
23256cca 557 return(seed);
558}
559
fa4d9e24 560uint32_t komodo_txtime(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
3eea72f2 561{
8d584a9c 562 CTxDestination address; CTransaction tx; uint256 hashBlock;
ce5dd547 563 *valuep = 0;
7637aa7f 564 if (!GetTransaction(hash, tx,
565#ifndef KOMODO_ZCASH
566 Params().GetConsensus(),
567#endif
568 hashBlock, true))
3eea72f2 569 {
4ff37947 570 //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
2ef19f04 571 return(0);
3eea72f2 572 }
1619474e 573 //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
2ef19f04 574 if ( n < tx.vout.size() )
8d584a9c 575 {
2ef19f04 576 *valuep = tx.vout[n].nValue;
fa4d9e24 577 if (ExtractDestination(tx.vout[n].scriptPubKey, address))
578 strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
8d584a9c 579 }
2ef19f04 580 return(tx.nLockTime);
3eea72f2 581}
582
0a953df2 583uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
584{
585 CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0;
586 *valuep = 0;
587 if (!GetTransaction(hash, tx,
588#ifndef KOMODO_ZCASH
589 Params().GetConsensus(),
590#endif
591 hashBlock, true))
592 {
593 //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
594 return(0);
595 }
ec894008 596 if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
0a953df2 597 txtime = pindex->nTime;
598 else txtime = tx.nLockTime;
599 //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
600 if ( n < tx.vout.size() )
601 {
602 *valuep = tx.vout[n].nValue;
603 if (ExtractDestination(tx.vout[n].scriptPubKey, address))
604 strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
605 }
606 return(txtime);
607}
608
3eea72f2 609void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
610{
7c130297 611 char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
e0440cc3 612 //fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight);
c93dc546 613 komodo_init(pindex->nHeight);
f3a1de3a 614 if ( (sp= komodo_stateptr(symbol,dest)) != 0 )
7a183152 615 {
9c432d66 616 //sp->rewinding = pindex->nHeight;
617 //fprintf(stderr,"-%d ",pindex->nHeight);
7a183152 618 } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL);
3eea72f2 619}
620
f24b36ca 621int32_t komodo_is_notarytx(const CTransaction& tx)
622{
faf51f1a 623 uint8_t *ptr; static uint8_t crypto777[33];
0554de3c 624 if ( tx.vout.size() > 0 )
625 {
f24b36ca 626#ifdef KOMODO_ZCASH
0554de3c 627 ptr = (uint8_t *)tx.vout[0].scriptPubKey.data();
f24b36ca 628#else
0554de3c 629 ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0];
f24b36ca 630#endif
0554de3c 631 if ( ptr != 0 )
303fbd20 632 {
faf51f1a 633 if ( crypto777[0] == 0 )
634 decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR);
0554de3c 635 if ( memcmp(ptr+1,crypto777,33) == 0 )
636 {
637 //printf("found notarytx\n");
638 return(1);
639 }
303fbd20 640 }
f24b36ca 641 }
303fbd20 642 return(0);
f24b36ca 643}
644
3eea72f2 645int32_t komodo_block2height(CBlock *block)
646{
e1501755 647 static uint32_t match,mismatch;
c52074f2 648 int32_t i,n,height2=-1,height = 0; uint8_t *ptr; CBlockIndex *pindex;
649 if ( (pindex= mapBlockIndex[block->GetHash()]) != 0 )
8a0b06f6 650 {
c52074f2 651 height2 = (int32_t)pindex->nHeight;
8a0b06f6 652 if ( height2 >= 0 )
653 return(height2);
654 }
0554de3c 655 if ( block->vtx[0].vin.size() > 0 )
656 {
189d9dee 657#ifdef KOMODO_ZCASH
0554de3c 658 ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
189d9dee 659#else
0554de3c 660 ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
189d9dee 661#endif
0554de3c 662 if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 )
3eea72f2 663 {
0554de3c 664 //for (i=0; i<6; i++)
665 // printf("%02x",ptr[i]);
666 n = ptr[0];
643bc61b 667 for (i=0; i<n; i++) // looks strange but this works
0554de3c 668 {
669 //03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
670 height += ((uint32_t)ptr[i+1] << (i*8));
671 //printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
672 }
643bc61b 673 //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
3eea72f2 674 }
0554de3c 675 //komodo_init(height);
3eea72f2 676 }
d4cc6fc3 677 if ( height != height2 )
c52074f2 678 {
f73e64e0 679 //fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch);
d4cc6fc3 680 mismatch++;
681 if ( height2 >= 0 )
f717835b 682 height = height2;
d4cc6fc3 683 } else match++;
3eea72f2 684 return(height);
685}
686
9464ac21 687int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
3eea72f2 688{
2dbf06e8 689 int32_t n;
0690e63e 690 if ( KOMODO_LOADINGBLOCKS == 0 )
691 memset(pubkey33,0xff,33);
692 else memset(pubkey33,0,33);
19848155 693 if ( block->vtx[0].vout.size() > 0 )
0554de3c 694 {
da00f2dd 695#ifdef KOMODO_ZCASH
19848155 696 uint8_t *ptr = (uint8_t *)block->vtx[0].vout[0].scriptPubKey.data();
da00f2dd 697#else
19848155 698 uint8_t *ptr = (uint8_t *)&block->vtx[0].vout[0].scriptPubKey[0];
da00f2dd 699#endif
0554de3c 700 //komodo_init(0);
19848155 701 n = block->vtx[0].vout[0].scriptPubKey.size();
0554de3c 702 if ( n == 35 )
9464ac21 703 {
0554de3c 704 memcpy(pubkey33,ptr+1,33);
9464ac21 705 return(1);
706 }
0554de3c 707 }
9464ac21 708 return(0);
3eea72f2 709}
710
d7093b33 711int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
875cf683 712{
713 block.SetNull();
714 // Open history file to read
715 CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION);
716 if (filein.IsNull())
717 return(-1);
718 // Read block
719 try { filein >> block; }
720 catch (const std::exception& e)
721 {
722 fprintf(stderr,"readblockfromdisk err B\n");
723 return(-1);
724 }
725 return(0);
726}
727
ae0bb3d3 728uint32_t komodo_chainactive_timestamp()
729{
730 if ( chainActive.Tip() != 0 )
731 return((uint32_t)chainActive.Tip()->GetBlockTime());
e34a9d43 732 else return(0);
ae0bb3d3 733}
734
7d44d3dd 735CBlockIndex *komodo_chainactive(int32_t height)
736{
5150cb47 737 if ( chainActive.Tip() != 0 )
7d44d3dd 738 {
5150cb47 739 if ( height <= chainActive.Tip()->nHeight )
740 return(chainActive[height]);
129d39b0 741 // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight);
d54aa57d 742 }
8c8a07ce 743 //fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height);
d54aa57d 744 return(0);
7d44d3dd 745}
746
747uint32_t komodo_heightstamp(int32_t height)
748{
0cb1d2da 749 CBlockIndex *ptr;
58bec1f9 750 if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 )
f21afd94 751 return(ptr->nTime);
b91ef9cf 752 //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height);
7d44d3dd 753 return(0);
754}
755
232506f7 756/*void komodo_pindex_init(CBlockIndex *pindex,int32_t height) gets data corrupted
141950a4 757{
5368f298 758 int32_t i,num; uint8_t pubkeys[64][33]; CBlock block;
5920762d 759 if ( pindex->didinit != 0 )
2b00bd23 760 return;
524e0280 761 //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->nHeight,pindex->notaryid,height);
065505b7 762 if ( pindex->didinit == 0 )
141950a4 763 {
326ddd86 764 pindex->notaryid = -1;
0690e63e 765 if ( KOMODO_LOADINGBLOCKS == 0 )
1f333439 766 memset(pindex->pubkey33,0xff,33);
0690e63e 767 else memset(pindex->pubkey33,0,33);
2b00bd23 768 if ( komodo_blockload(block,pindex) == 0 )
ace61bc1 769 {
19848155 770 komodo_block2pubkey33(pindex->pubkey33,&block);
3884efe7 771 //for (i=0; i<33; i++)
772 // fprintf(stderr,"%02x",pindex->pubkey33[i]);
773 //fprintf(stderr," set pubkey at height %d/%d\n",pindex->nHeight,height);
702f7543 774 //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 )
232506f7 775 // pindex->didinit = (KOMODO_LOADINGBLOCKS == 0);
524e0280 776 } // else fprintf(stderr,"error loading block at %d/%d",pindex->nHeight,height);
2b00bd23 777 }
065505b7 778 if ( pindex->didinit != 0 && pindex->nHeight >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->nHeight,(uint32_t)pindex->nTime)) > 0 )
2b00bd23 779 {
780 for (i=0; i<num; i++)
141950a4 781 {
2b00bd23 782 if ( memcmp(pubkeys[i],pindex->pubkey33,33) == 0 )
141950a4 783 {
2b00bd23 784 pindex->notaryid = i;
785 break;
141950a4 786 }
787 }
524e0280 788 if ( 0 && i == num )
ace61bc1 789 {
790 for (i=0; i<33; i++)
791 fprintf(stderr,"%02x",pindex->pubkey33[i]);
792 fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->nHeight,height);
793 }
141950a4 794 }
232506f7 795}*/
141950a4 796
3eea72f2 797void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
798{
232506f7 799 int32_t num,i; CBlock block;
3eea72f2 800 memset(pubkey33,0,33);
071f1be1 801 if ( pindex != 0 )
3eea72f2 802 {
232506f7 803 if ( komodo_blockload(block,pindex) == 0 )
804 komodo_block2pubkey33(pubkey33,&block);
3eea72f2 805 }
806}
807
da9fce3e 808/*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33)
4a4e912b 809{
149a4d64 810 int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33];
3e7e3109 811 if ( (pindex= chainActive[height]) != 0 )
fc318ffe 812 {
d74896c5 813 if ( pindex->didinit != 0 )
5e0e5f85 814 {
149a4d64 815 if ( destpubkey33 != 0 )
816 memcpy(destpubkey33,pindex->pubkey33,33);
3e7e3109 817 return(pindex->notaryid);
5e0e5f85 818 }
149a4d64 819 komodo_index2pubkey33(pubkey33,pindex,height);
820 if ( destpubkey33 != 0 )
821 memcpy(destpubkey33,pindex->pubkey33,33);
822 if ( pindex->didinit != 0 )
823 return(pindex->notaryid);
5e0e5f85 824 timestamp = pindex->GetBlockTime();
eb7171f5 825 if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 )
826 {
827 for (i=0; i<num; i++)
828 if ( memcmp(pubkeys[i],pubkey33,33) == 0 )
829 return(i);
1746e25c 830 }
dac1ef88 831 }
0f29cbd6 832 fprintf(stderr,"komodo_minerid height.%d null pindex\n",height);
8eaa7b03 833 return(komodo_electednotary(&numnotaries,pubkey33,height,timestamp));
da9fce3e 834}*/
4a4e912b 835
a30dd993 836int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height)
353af8aa 837{
178618db 838 int32_t i,j,n,duplicate; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33];
353af8aa 839 memset(mids,-1,sizeof(*mids)*66);
1481a43d 840 n = komodo_notaries(notarypubs33,height,0);
353af8aa 841 for (i=duplicate=0; i<66; i++)
842 {
3c525df1 843 if ( (pindex= komodo_chainactive(height-i)) != 0 )
353af8aa 844 {
a30dd993 845 blocktimes[i] = pindex->nTime;
da9fce3e 846 if ( komodo_blockload(block,pindex) == 0 )
847 {
848 komodo_block2pubkey33(pubkeys[i],&block);
849 for (j=0; j<n; j++)
850 {
178618db 851 if ( memcmp(notarypubs33[j],pubkeys[i],33) == 0 )
da9fce3e 852 {
853 mids[i] = j;
854 (*nonzpkeysp)++;
855 break;
856 }
857 }
1481a43d 858 } else fprintf(stderr,"couldnt load block.%d\n",height);
353af8aa 859 if ( mids[0] >= 0 && i > 0 && mids[i] == mids[0] )
860 duplicate++;
3c525df1 861 }
353af8aa 862 }
f2805ceb 863 if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) )
353af8aa 864 return(1);
865 else return(0);
866}
867
df03549d 868int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width)
dbaf1154 869{
df03549d 870 int32_t i,j,n,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33];
871 numnotaries = komodo_notaries(notarypubs33,height,0);
872 for (i=nonz=0; i<width; i++,n++)
873 {
874 if ( height-i <= 0 )
875 continue;
876 if ( (pindex= komodo_chainactive(height-width+i+1)) != 0 )
877 {
878 if ( komodo_blockload(block,pindex) == 0 )
879 {
880 komodo_block2pubkey33(pubkey33,&block);
881 for (j=0; j<numnotaries; j++)
882 {
883 if ( memcmp(notarypubs33[j],pubkey33,33) == 0 )
884 {
885 minerids[nonz++] = j;
886 break;
887 }
888 }
0d8dc237 889 if ( j == numnotaries )
890 minerids[nonz++] = j;
df03549d 891 } else fprintf(stderr,"couldnt load block.%d\n",height);
892 }
893 }
894 return(nonz);
dbaf1154 895}
896
dac3c30c 897int32_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)
4a4e912b 898{
442215b4 899 int32_t i,j,notaryid=0,minerid,limit,nid; uint8_t destpubkey33[33];
dac3c30c 900 komodo_chosennotary(&notaryid,height,pubkey33,blocktimes[0]);
cb19d181 901 if ( height >= 82000 )
82f82d3f 902 {
442215b4 903 if ( notaryid >= 0 )
82f82d3f 904 {
905 for (i=1; i<66; i++)
906 {
442215b4 907 if ( mids[i] == notaryid )
82f82d3f 908 {
3c89a023 909 if ( height > 792000 )
0f5e787b 910 {
911 for (j=0; j<66; j++)
912 fprintf(stderr,"%d ",mids[j]);
913 fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i);
861119a1 914 return(-1);
0f5e787b 915 } else break;
82f82d3f 916 }
917 }
a658d926 918 if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 )
3ad8d247 919 {
26d9f4c3 920 if ( height > 807000 )
a658d926 921 return(-2);
fb64a588 922 }
923 return(1);
82f82d3f 924 } else return(0);
925 }
442215b4 926 else
4a4e912b 927 {
428a3934 928 if ( height >= 34000 && notaryid >= 0 )
4a4e912b 929 {
428a3934 930 if ( height < 79693 )
931 limit = 64;
932 else if ( height < 82000 )
933 limit = 8;
934 else limit = 66;
935 for (i=1; i<limit; i++)
66e3c532 936 {
70ebf02a 937 komodo_chosennotary(&nid,height-i,pubkey33,blocktimes[i]);
428a3934 938 if ( nid == notaryid )
939 {
79fb8179 940 //for (j=0; j<66; j++)
941 // fprintf(stderr,"%d ",mids[j]);
942 //fprintf(stderr,"ht.%d repeat mids[%d] nid.%d notaryid.%d\n",height-i,i,nid,notaryid);
428a3934 943 if ( height > 225000 )
944 return(-1);
945 }
66e3c532 946 }
428a3934 947 //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit);
948 return(1);
4a4e912b 949 }
4a4e912b 950 }
951 return(0);
952}
953
51dab149 954int32_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)
0ab5b335 955{
aa5ca001 956 int32_t depth,notarized_ht; uint256 MoM,kmdtxid;
51dab149 957 depth = komodo_MoMdata(&notarized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip);
0ab5b335 958 memset(MoMp,0,sizeof(*MoMp));
b3548b52 959 memset(kmdtxidp,0,sizeof(*kmdtxidp));
0ab5b335 960 *notarized_heightp = 0;
1b9f98cd 961 if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht )
0ab5b335 962 {
963 *MoMp = MoM;
964 *notarized_heightp = notarized_ht;
aa5ca001 965 *kmdtxidp = kmdtxid;
0ab5b335 966 }
967 return(depth);
968}
969
b62d7030 970int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
971{
c52074f2 972 int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex;
d82623d2 973 if ( (pindex= chainActive.Tip()) == 0 )
974 return(-1);
975 notarized_height = komodo_notarizeddata(pindex->nHeight,&notarized_hash,&notarized_desttxid);
b62d7030 976 *notarized_heightp = notarized_height;
aba9ea3c 977 if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
b62d7030 978 {
d82623d2 979 //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
b62d7030 980 if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
981 {
982 if ( nHeight < notarized_height )
983 {
2c5af2cd 984 //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
b62d7030 985 return(-1);
986 }
987 else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
988 {
beb911ec 989 fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
b62d7030 990 return(-1);
991 }
ccff4876 992 } //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);
beb911ec 993 }
dc836ee4 994 //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 )
995 // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight);
b62d7030 996 return(0);
997}
485e48ca 998
83da1e16 999uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n)
c1c95e36 1000{
1001 LOCK(cs_main);
1002 CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex;
63c93b0c 1003 *txheighttimep = *txheightp = *tiptimep = 0;
1004 *valuep = 0;
c1c95e36 1005 if ( !GetTransaction(hash,tx,hashBlock,true) )
1006 return(0);
1007 uint32_t locktime = 0;
1008 if ( n < tx.vout.size() )
1009 {
c60397dd 1010 if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
c1c95e36 1011 {
1012 *valuep = tx.vout[n].nValue;
1013 *txheightp = pindex->nHeight;
83da1e16 1014 *txheighttimep = pindex->nTime;
c60397dd 1015 if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 )
1016 *tiptimep = (uint32_t)tipindex->nTime;
c1c95e36 1017 locktime = tx.nLockTime;
1f52f946 1018 //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep);
c1c95e36 1019 }
1020 }
1021 return(locktime);
1022}
1023
1024uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
c60397dd 1025
1026uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight)
c1c95e36 1027{
c60397dd 1028 uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex;
1029 if ( (pindex= chainActive[tipheight]) != 0 )
1030 tiptime = (uint32_t)pindex->nTime;
72070c94 1031 else fprintf(stderr,"cant find height[%d]\n",tipheight);
83da1e16 1032 if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 )
c1c95e36 1033 {
798f28c7 1034 if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) )
1035 return(komodo_interest(*txheightp,value,*locktimep,tiptime));
c1c95e36 1036 //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 1037 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);
1038 }
c1c95e36 1039 return(0);
1040}
8a7f7063 1041
1042int32_t komodo_isrealtime(int32_t *kmdheightp)
1043{
d82623d2 1044 struct komodo_state *sp; CBlockIndex *pindex;
8a7c9241 1045 if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 )
ffbc2f00 1046 *kmdheightp = sp->CURRENT_HEIGHT;
1047 else *kmdheightp = 0;
1b5b89ba 1048 if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() )
8a7f7063 1049 return(1);
1050 else return(0);
1051}
14aa6cc0 1052
99d7ed25 1053int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag)
14aa6cc0 1054{
837aaaec 1055 if ( KOMODO_REWIND == 0 && (ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED != 0) && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
14aa6cc0 1056 {
837aaaec 1057 if ( txheight > 246748 || ASSETCHAINS_STAKED != 0 )
14aa6cc0 1058 {
837aaaec 1059 if ( txheight < 247205 && ASSETCHAINS_STAKED == 0 )
39d28b06 1060 cmptime -= 16000;
bd070d8b 1061 if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME )
14aa6cc0 1062 {
531b9293 1063 if ( tx.nLockTime != 1477258935 && dispflag != 0 )
14aa6cc0 1064 {
bd070d8b 1065 fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(uint32_t)tx.nLockTime,cmptime);
14aa6cc0 1066 }
1067 return(-1);
1068 }
948ad8f3 1069 if ( 0 && dispflag != 0 )
bd070d8b 1070 fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-KOMODO_MAXMEMPOOLTIME)),(int32_t)tx.nLockTime,cmptime);
14aa6cc0 1071 }
14aa6cc0 1072 }
1073 return(0);
1074}
ec5ed2f7 1075
18443f69 1076/*
9464ac21 1077 komodo_checkPOW (fast) is called early in the process and should only refer to data immediately available. it is a filter to prevent bad blocks from going into the local DB. The more blocks we can filter out at this stage, the less junk in the local DB that will just get purged later on.
18443f69 1078
1079 komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass
1080
1081 commission must be in coinbase.vout[1] and must be >= 10000 sats
1082 PoS stake must be without txfee and in the last tx in the block at vout[0]
1083 PoW mining on PoS chain must solve a harder diff that adjusts, but never less than KOMODO_POWMINMULT
1084 */
1085#define KOMODO_POWMINMULT 16
1086
1087uint64_t komodo_commission(const CBlock *pblock)
1088{
1089 int32_t i,j,n=0,txn_count; uint64_t commission,total = 0;
1090 txn_count = pblock->vtx.size();
1091 for (i=0; i<txn_count; i++)
1092 {
3acce042 1093 n = pblock->vtx[i].vout.size();
18443f69 1094 for (j=0; j<n; j++)
1095 {
1096 //fprintf(stderr,"(%d %.8f).%d ",i,dstr(block.vtx[i].vout[j].nValue),j);
1097 if ( i != 0 || j != 1 )
1098 total += pblock->vtx[i].vout[j].nValue;
1099 }
1100 }
1101 //fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN));
1102 commission = ((total * ASSETCHAINS_COMMISSION) / COIN);
1103 if ( commission < 10000 )
1104 commission = 0;
1105 return(commission);
1106}
1107
acbc7a94 1108uint32_t komodo_segid32(char *coinaddr)
1109{
1110 bits256 addrhash;
3001f999 1111 vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr));
acbc7a94 1112 return(addrhash.uints[0]);
1113}
1114
049e24ce 1115int8_t komodo_segid(int32_t height)
1116{
86f88c4f 1117 CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; int8_t segid = -1;
049e24ce 1118 if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 )
1119 {
1120 if ( komodo_blockload(block,pindex) == 0 )
1121 {
86f88c4f 1122 txn_count = block.vtx.size();
1123 if ( txn_count > 1 && block.vtx[txn_count-1].vin.size() == 1 && block.vtx[txn_count-1].vout.size() == 1 )
049e24ce 1124 {
86f88c4f 1125 txid = block.vtx[txn_count-1].vin[0].prevout.hash;
1126 vout = block.vtx[txn_count-1].vin[0].prevout.n;
049e24ce 1127 txtime = komodo_txtime(&value,txid,vout,destaddr);
86f88c4f 1128 if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
049e24ce 1129 {
1130 strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
86f88c4f 1131 if ( strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value )
049e24ce 1132 {
1133 segid = komodo_segid32(voutaddr) & 0x3f;
1134 }
1135 } else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height);
1136 }
1137 }
1138 }
1139 return(segid);
1140}
1141
1142int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n)
1143{
1144 static uint8_t prevhashbuf[100]; static int32_t prevheight;
1145 int32_t i;
1146 if ( height == prevheight && n == 100 )
1147 memcpy(hashbuf,prevhashbuf,100);
1148 else
1149 {
1150 memset(hashbuf,0xff,n);
1151 for (i=0; i<n; i++)
1152 {
1153 hashbuf[i] = (uint8_t)komodo_segid(height+i);
bf915dce 1154 //fprintf(stderr,"%02x ",hashbuf[i]);
049e24ce 1155 }
1156 if ( n == 100 )
1157 {
1158 memcpy(prevhashbuf,hashbuf,100);
1159 prevheight = height;
bf915dce 1160 //fprintf(stderr,"segids.%d\n",height);
049e24ce 1161 }
1162 }
1163}
1164
97a337f7 1165uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr)
049e24ce 1166{
0999e80e 1167 bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio; uint256 hash,pasthash; int32_t diff=0,segid,minage,i,iter=0; uint32_t txtime,winner = 0 ; uint64_t value,coinage;
0a953df2 1168 txtime = komodo_txtime2(&value,txid,vout,address);
89931e6e 1169 if ( validateflag == 0 && blocktime < GetAdjustedTime() )
f1d8e4b6 1170 blocktime = GetAdjustedTime();
97a337f7 1171 if ( blocktime < prevtime+3 )
1172 blocktime = prevtime+3;
049e24ce 1173 if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
1174 {
01994dba 1175 //fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
049e24ce 1176 return(0);
1177 }
97a337f7 1178 if ( value < SATOSHIDEN )
1179 return(0);
a03465f6 1180 value /= SATOSHIDEN;
84f19b77 1181 mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
1182 ratio = (mindiff / bnTarget);
049e24ce 1183 if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
1184 minage = 6000;
049e24ce 1185 vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
1186 segid = ((nHeight + addrhash.uints[0]) & 0x3f);
1187 komodo_segids(hashbuf,nHeight-101,100);
1188 memcpy(&hashbuf[100],&addrhash,sizeof(addrhash));
1189 memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid));
1190 memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout));
1191 vcalc_sha256(0,(uint8_t *)&hash,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout));
1192 for (iter=0; iter<3600; iter++)
1193 {
1194 diff = (iter + blocktime - txtime - minage);
f6567e80 1195 if ( diff < 0 )
1196 diff = 60;
1197 else if ( diff > 3600*24*30 )
5e90f445 1198 {
01994dba 1199 //printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage);
049e24ce 1200 diff = 3600*24*30;
5e90f445 1201 }
049e24ce 1202 if ( iter > 0 )
1203 diff += segid*2;
1204 if ( blocktime+iter+segid*2 < txtime+minage )
1205 continue;
bfa19436 1206 coinage = (value * diff);
38cbe99b 1207 hashval = ratio * (UintToArith256(hash) / arith_uint256(coinage+1));
049e24ce 1208 if ( hashval <= bnTarget )
1209 {
1210 winner = 1;
1211 if ( validateflag == 0 )
1212 {
1213 blocktime += iter;
1214 blocktime += segid * 2;
1215 }
1216 break;
1217 }
1218 if ( validateflag != 0 )
1219 {
84f19b77 1220 for (i=31; i>=24; i--)
1221 fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
01994dba 1222 fprintf(stderr," vs ");
84f19b77 1223 for (i=31; i>=24; i--)
1224 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
01994dba 1225 fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff);
049e24ce 1226 break;
1227 }
1228 }
1229 //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
01994dba 1230 if ( 0 )
049e24ce 1231 {
1232 for (i=31; i>=24; i--)
1233 fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
1234 fprintf(stderr," vs ");
1235 for (i=31; i>=24; i--)
1236 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
bfa19436 1237 fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff);
049e24ce 1238 }
1239 if ( nHeight < 10 )
1240 return(blocktime);
1241 return(blocktime * winner);
1242}
1243
18443f69 1244arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc)
1245{
97a337f7 1246 CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,ht,percPoS,diff,val;
18443f69 1247 *percPoSp = percPoS = 0;
8daf7caf 1248 if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) )
96df006a 1249 return(target);
18443f69 1250 sum = arith_uint256(0);
1251 ave = sum;
97a337f7 1252 easydiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
18443f69 1253 for (i=n=0; i<100; i++)
1254 {
1255 ht = height - 100 + i;
e83bf6b3 1256 if ( ht <= 1 )
1257 continue;
18443f69 1258 if ( (pindex= komodo_chainactive(ht)) != 0 )
1259 {
1260 bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow);
1261 bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT));
1262 hashval = UintToArith256(pindex->GetBlockHash());
3753f568 1263 if ( hashval <= bnTarget ) // PoW is never as easy as PoS/16, some PoS will be counted as PoW
18443f69 1264 {
f2c1ac06 1265 if ( ASSETCHAINS_STAKED < 100 )
1266 fprintf(stderr,"1");
18443f69 1267 sum += hashval;
1268 n++;
689a24a7 1269 }
1270 else
1271 {
1272 percPoS++;
f2c1ac06 1273 if ( ASSETCHAINS_STAKED < 100 )
1274 fprintf(stderr,"0");
689a24a7 1275 }
f2c1ac06 1276 if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 )
f225a9ba 1277 fprintf(stderr," %d, ",percPoS);
18443f69 1278 }
1279 }
3753f568 1280 if ( n < 100 )
1281 percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
f2c1ac06 1282 if ( ASSETCHAINS_STAKED < 100 )
1283 fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height);
18443f69 1284 *percPoSp = percPoS;
1285 target = (target / arith_uint256(KOMODO_POWMINMULT));
1286 if ( n > 0 )
1287 {
1288 ave = (sum / arith_uint256(n));
1289 if ( ave > target )
1290 ave = target;
1291 } else return(target);
1292 if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
1293 {
181e67c6 1294 bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc);
f2c1ac06 1295 if ( ASSETCHAINS_STAKED < 100 )
18443f69 1296 {
1297 for (i=31; i>=24; i--)
1298 fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
1299 fprintf(stderr," increase diff -> ");
1300 for (i=31; i>=24; i--)
1301 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1302 fprintf(stderr," floor diff ");
1303 for (i=31; i>=24; i--)
1304 fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
1305 fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
1306 }
1307 }
1308 else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget
1309 {
97a337f7 1310 bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
23b680a0 1311 if ( 1 )
18443f69 1312 {
1313 for (i=31; i>=24; i--)
1314 fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
1315 fprintf(stderr," decrease diff -> ");
1316 for (i=31; i>=24; i--)
1317 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1318 fprintf(stderr," floor diff ");
1319 for (i=31; i>=24; i--)
1320 fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
1321 fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
1322 }
1323 }
1324 else bnTarget = ave; // recent ave is perfect
1325 return(bnTarget);
1326}
1327
3acce042 1328int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget)
18443f69 1329{
2808b68f 1330 CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible,isPoS = 0; uint64_t value; CTxDestination voutaddress;
6ac49724 1331 if ( ASSETCHAINS_STAKED == 100 && height < 200 )
1332 return(1);
18443f69 1333 txn_count = pblock->vtx.size();
feefa2d3 1334 if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 )
18443f69 1335 {
1336 if ( prevtime == 0 )
1337 {
1338 if ( (previndex= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
1339 prevtime = (uint32_t)previndex->nTime;
1340 }
1341 txid = pblock->vtx[txn_count-1].vin[0].prevout.hash;
1342 vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
1343 if ( prevtime != 0 )
1344 {
1345 eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime,(char *)"");
1346 if ( eligible == 0 || eligible > pblock->nTime )
1347 {
e8dd12a1 1348 //fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime));
18443f69 1349 } else isPoS = 1;
1350 }
9c2f6f11 1351 if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx
18443f69 1352 {
1353 txtime = komodo_txtime(&value,txid,vout,destaddr);
1354 if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
1355 {
2808b68f 1356 strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
3acce042 1357 if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[txn_count-1].vout[0].nValue == value )
18443f69 1358 isPoS = 1; // close enough for a pre-filter
42c0fc6a 1359 //else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue));
18443f69 1360 } else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height);
764576d5 1361 } //else return(-1);
18443f69 1362 }
ffd6dd51 1363 //fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS);
18443f69 1364 return(isPoS);
1365}
1366
fb6bb4e8 1367int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
1368{
1369 int64_t checktoshis=0; uint8_t *script;
1370 if ( ASSETCHAINS_COMMISSION != 0 )
1371 {
1372 checktoshis = komodo_commission(pblock);
1373 if ( checktoshis > 10000 && pblock->vtx[0].vout.size() != 2 )
1374 return(-1);
1375 else if ( checktoshis != 0 )
1376 {
1377 script = (uint8_t *)pblock->vtx[0].vout[1].scriptPubKey.data();
1378 if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
1379 return(-1);
1380 if ( pblock->vtx[0].vout[1].nValue != checktoshis )
1381 {
1382 fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue));
1383 return(-1);
1384 }
1385 }
1386 }
1387 return(checktoshis);
1388}
1389
3fdb3782
SS
1390bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0;
1391
18443f69 1392int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
1393{
9464ac21 1394 uint256 hash; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev;
18443f69 1395 if ( !CheckEquihashSolution(pblock, Params()) )
1396 {
1397 fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height);
1398 return(-1);
1399 }
ec5b59fd 1400 hash = pblock->GetHash();
45ee62cb 1401 bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow);
9464ac21 1402 bhash = UintToArith256(hash);
1403 possible = komodo_block2pubkey33(pubkey33,pblock);
c685d692 1404 //fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget);
28b18b61 1405 if ( height == 0 )
f1b57a6e 1406 {
28b18b61 1407 if ( slowflag != 0 )
1408 return(0);
1409 if ( (pprev= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
1410 height = pprev->nHeight + 1;
1411 if ( height == 0 )
1412 return(0);
f1b57a6e 1413 }
2c089649 1414 if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget )
18443f69 1415 {
1416 failed = 1;
9464ac21 1417 if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case
18443f69 1418 {
1419 if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 )
1420 {
1421 for (i=0; i<n; i++)
1422 if ( memcmp(pubkey33,pubkeys[i],33) == 0 )
1423 {
1424 notaryid = i;
1425 break;
1426 }
1427 }
1428 }
9464ac21 1429 else if ( possible == 0 || ASSETCHAINS_SYMBOL[0] != 0 )
1430 {
f02af889 1431 if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW )
1432 return(0);
2ba9de01 1433 if ( ASSETCHAINS_STAKED == 0 ) // komodo_is_PoSblock will check bnTarget
1434 return(-1);
9464ac21 1435 }
18443f69 1436 }
a3d08df0 1437 if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW
18443f69 1438 {
3acce042 1439 if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget)) == 0 )
18443f69 1440 {
f02af889 1441 if ( ASSETCHAINS_STAKED == 100 && height > 130 ) // only PoS allowed! POSTEST64
18443f69 1442 return(-1);
1443 else
1444 {
1445 if ( slowflag != 0 )
1446 bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
e83bf6b3 1447 else if ( height > 100 )
1448 bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); // lower bound
18443f69 1449 if ( bhash > bnTarget )
1450 {
1451 for (i=31; i>=16; i--)
2808b68f 1452 fprintf(stderr,"%02x",((uint8_t *)&bhash)[i]);
18443f69 1453 fprintf(stderr," > ");
1454 for (i=31; i>=16; i--)
1455 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1456 fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED);
1457 return(-1);
1458 }
1459 }
3acce042 1460 } else if ( is_PoSblock < 0 )
18443f69 1461 return(-1);
1462 }
d9f176ac 1463 if ( failed == 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
18443f69 1464 {
d9f176ac 1465 if ( height == 1 )
18443f69 1466 {
d9f176ac 1467 script = (uint8_t *)pblock->vtx[0].vout[0].scriptPubKey.data();
18443f69 1468 if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
1469 return(-1);
d9f176ac 1470 }
c9855c14 1471 else
1472 {
1473 if ( komodo_checkcommission(pblock,height) < 0 )
18443f69 1474 return(-1);
18443f69 1475 }
1476 }
c685d692 1477 //fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
1478 if ( failed != 0 && possible == 0 && notaryid < 0 )
18443f69 1479 return(-1);
1480 else return(0);
1481}
1482
This page took 0.573771 seconds and 4 git commands to generate.