]> Git Repo - VerusCoin.git/blame - src/komodo_bitcoind.h
-print
[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
583void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
584{
7c130297 585 char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
e0440cc3 586 //fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight);
c93dc546 587 komodo_init(pindex->nHeight);
f3a1de3a 588 if ( (sp= komodo_stateptr(symbol,dest)) != 0 )
7a183152 589 {
9c432d66 590 //sp->rewinding = pindex->nHeight;
591 //fprintf(stderr,"-%d ",pindex->nHeight);
7a183152 592 } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL);
3eea72f2 593}
594
f24b36ca 595int32_t komodo_is_notarytx(const CTransaction& tx)
596{
faf51f1a 597 uint8_t *ptr; static uint8_t crypto777[33];
0554de3c 598 if ( tx.vout.size() > 0 )
599 {
f24b36ca 600#ifdef KOMODO_ZCASH
0554de3c 601 ptr = (uint8_t *)tx.vout[0].scriptPubKey.data();
f24b36ca 602#else
0554de3c 603 ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0];
f24b36ca 604#endif
0554de3c 605 if ( ptr != 0 )
303fbd20 606 {
faf51f1a 607 if ( crypto777[0] == 0 )
608 decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR);
0554de3c 609 if ( memcmp(ptr+1,crypto777,33) == 0 )
610 {
611 //printf("found notarytx\n");
612 return(1);
613 }
303fbd20 614 }
f24b36ca 615 }
303fbd20 616 return(0);
f24b36ca 617}
618
3eea72f2 619int32_t komodo_block2height(CBlock *block)
620{
e1501755 621 static uint32_t match,mismatch;
c52074f2 622 int32_t i,n,height2=-1,height = 0; uint8_t *ptr; CBlockIndex *pindex;
623 if ( (pindex= mapBlockIndex[block->GetHash()]) != 0 )
8a0b06f6 624 {
c52074f2 625 height2 = (int32_t)pindex->nHeight;
8a0b06f6 626 if ( height2 >= 0 )
627 return(height2);
628 }
0554de3c 629 if ( block->vtx[0].vin.size() > 0 )
630 {
189d9dee 631#ifdef KOMODO_ZCASH
0554de3c 632 ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
189d9dee 633#else
0554de3c 634 ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
189d9dee 635#endif
0554de3c 636 if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 )
3eea72f2 637 {
0554de3c 638 //for (i=0; i<6; i++)
639 // printf("%02x",ptr[i]);
640 n = ptr[0];
643bc61b 641 for (i=0; i<n; i++) // looks strange but this works
0554de3c 642 {
643 //03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
644 height += ((uint32_t)ptr[i+1] << (i*8));
645 //printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
646 }
643bc61b 647 //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
3eea72f2 648 }
0554de3c 649 //komodo_init(height);
3eea72f2 650 }
d4cc6fc3 651 if ( height != height2 )
c52074f2 652 {
f73e64e0 653 //fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch);
d4cc6fc3 654 mismatch++;
655 if ( height2 >= 0 )
f717835b 656 height = height2;
d4cc6fc3 657 } else match++;
3eea72f2 658 return(height);
659}
660
9464ac21 661int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
3eea72f2 662{
2dbf06e8 663 int32_t n;
0690e63e 664 if ( KOMODO_LOADINGBLOCKS == 0 )
665 memset(pubkey33,0xff,33);
666 else memset(pubkey33,0,33);
19848155 667 if ( block->vtx[0].vout.size() > 0 )
0554de3c 668 {
da00f2dd 669#ifdef KOMODO_ZCASH
19848155 670 uint8_t *ptr = (uint8_t *)block->vtx[0].vout[0].scriptPubKey.data();
da00f2dd 671#else
19848155 672 uint8_t *ptr = (uint8_t *)&block->vtx[0].vout[0].scriptPubKey[0];
da00f2dd 673#endif
0554de3c 674 //komodo_init(0);
19848155 675 n = block->vtx[0].vout[0].scriptPubKey.size();
0554de3c 676 if ( n == 35 )
9464ac21 677 {
0554de3c 678 memcpy(pubkey33,ptr+1,33);
9464ac21 679 return(1);
680 }
0554de3c 681 }
9464ac21 682 return(0);
3eea72f2 683}
684
d7093b33 685int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
875cf683 686{
687 block.SetNull();
688 // Open history file to read
689 CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION);
690 if (filein.IsNull())
691 return(-1);
692 // Read block
693 try { filein >> block; }
694 catch (const std::exception& e)
695 {
696 fprintf(stderr,"readblockfromdisk err B\n");
697 return(-1);
698 }
699 return(0);
700}
701
ae0bb3d3 702uint32_t komodo_chainactive_timestamp()
703{
704 if ( chainActive.Tip() != 0 )
705 return((uint32_t)chainActive.Tip()->GetBlockTime());
e34a9d43 706 else return(0);
ae0bb3d3 707}
708
7d44d3dd 709CBlockIndex *komodo_chainactive(int32_t height)
710{
5150cb47 711 if ( chainActive.Tip() != 0 )
7d44d3dd 712 {
5150cb47 713 if ( height <= chainActive.Tip()->nHeight )
714 return(chainActive[height]);
129d39b0 715 // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight);
d54aa57d 716 }
8c8a07ce 717 //fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height);
d54aa57d 718 return(0);
7d44d3dd 719}
720
721uint32_t komodo_heightstamp(int32_t height)
722{
0cb1d2da 723 CBlockIndex *ptr;
58bec1f9 724 if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 )
f21afd94 725 return(ptr->nTime);
b91ef9cf 726 //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height);
7d44d3dd 727 return(0);
728}
729
232506f7 730/*void komodo_pindex_init(CBlockIndex *pindex,int32_t height) gets data corrupted
141950a4 731{
5368f298 732 int32_t i,num; uint8_t pubkeys[64][33]; CBlock block;
5920762d 733 if ( pindex->didinit != 0 )
2b00bd23 734 return;
524e0280 735 //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->nHeight,pindex->notaryid,height);
065505b7 736 if ( pindex->didinit == 0 )
141950a4 737 {
326ddd86 738 pindex->notaryid = -1;
0690e63e 739 if ( KOMODO_LOADINGBLOCKS == 0 )
1f333439 740 memset(pindex->pubkey33,0xff,33);
0690e63e 741 else memset(pindex->pubkey33,0,33);
2b00bd23 742 if ( komodo_blockload(block,pindex) == 0 )
ace61bc1 743 {
19848155 744 komodo_block2pubkey33(pindex->pubkey33,&block);
3884efe7 745 //for (i=0; i<33; i++)
746 // fprintf(stderr,"%02x",pindex->pubkey33[i]);
747 //fprintf(stderr," set pubkey at height %d/%d\n",pindex->nHeight,height);
702f7543 748 //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 )
232506f7 749 // pindex->didinit = (KOMODO_LOADINGBLOCKS == 0);
524e0280 750 } // else fprintf(stderr,"error loading block at %d/%d",pindex->nHeight,height);
2b00bd23 751 }
065505b7 752 if ( pindex->didinit != 0 && pindex->nHeight >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->nHeight,(uint32_t)pindex->nTime)) > 0 )
2b00bd23 753 {
754 for (i=0; i<num; i++)
141950a4 755 {
2b00bd23 756 if ( memcmp(pubkeys[i],pindex->pubkey33,33) == 0 )
141950a4 757 {
2b00bd23 758 pindex->notaryid = i;
759 break;
141950a4 760 }
761 }
524e0280 762 if ( 0 && i == num )
ace61bc1 763 {
764 for (i=0; i<33; i++)
765 fprintf(stderr,"%02x",pindex->pubkey33[i]);
766 fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->nHeight,height);
767 }
141950a4 768 }
232506f7 769}*/
141950a4 770
3eea72f2 771void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
772{
232506f7 773 int32_t num,i; CBlock block;
3eea72f2 774 memset(pubkey33,0,33);
071f1be1 775 if ( pindex != 0 )
3eea72f2 776 {
232506f7 777 if ( komodo_blockload(block,pindex) == 0 )
778 komodo_block2pubkey33(pubkey33,&block);
3eea72f2 779 }
780}
781
da9fce3e 782/*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33)
4a4e912b 783{
149a4d64 784 int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33];
3e7e3109 785 if ( (pindex= chainActive[height]) != 0 )
fc318ffe 786 {
d74896c5 787 if ( pindex->didinit != 0 )
5e0e5f85 788 {
149a4d64 789 if ( destpubkey33 != 0 )
790 memcpy(destpubkey33,pindex->pubkey33,33);
3e7e3109 791 return(pindex->notaryid);
5e0e5f85 792 }
149a4d64 793 komodo_index2pubkey33(pubkey33,pindex,height);
794 if ( destpubkey33 != 0 )
795 memcpy(destpubkey33,pindex->pubkey33,33);
796 if ( pindex->didinit != 0 )
797 return(pindex->notaryid);
5e0e5f85 798 timestamp = pindex->GetBlockTime();
eb7171f5 799 if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 )
800 {
801 for (i=0; i<num; i++)
802 if ( memcmp(pubkeys[i],pubkey33,33) == 0 )
803 return(i);
1746e25c 804 }
dac1ef88 805 }
0f29cbd6 806 fprintf(stderr,"komodo_minerid height.%d null pindex\n",height);
8eaa7b03 807 return(komodo_electednotary(&numnotaries,pubkey33,height,timestamp));
da9fce3e 808}*/
4a4e912b 809
a30dd993 810int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height)
353af8aa 811{
178618db 812 int32_t i,j,n,duplicate; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33];
353af8aa 813 memset(mids,-1,sizeof(*mids)*66);
1481a43d 814 n = komodo_notaries(notarypubs33,height,0);
353af8aa 815 for (i=duplicate=0; i<66; i++)
816 {
3c525df1 817 if ( (pindex= komodo_chainactive(height-i)) != 0 )
353af8aa 818 {
a30dd993 819 blocktimes[i] = pindex->nTime;
da9fce3e 820 if ( komodo_blockload(block,pindex) == 0 )
821 {
822 komodo_block2pubkey33(pubkeys[i],&block);
823 for (j=0; j<n; j++)
824 {
178618db 825 if ( memcmp(notarypubs33[j],pubkeys[i],33) == 0 )
da9fce3e 826 {
827 mids[i] = j;
828 (*nonzpkeysp)++;
829 break;
830 }
831 }
1481a43d 832 } else fprintf(stderr,"couldnt load block.%d\n",height);
353af8aa 833 if ( mids[0] >= 0 && i > 0 && mids[i] == mids[0] )
834 duplicate++;
3c525df1 835 }
353af8aa 836 }
f2805ceb 837 if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) )
353af8aa 838 return(1);
839 else return(0);
840}
841
df03549d 842int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width)
dbaf1154 843{
df03549d 844 int32_t i,j,n,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33];
845 numnotaries = komodo_notaries(notarypubs33,height,0);
846 for (i=nonz=0; i<width; i++,n++)
847 {
848 if ( height-i <= 0 )
849 continue;
850 if ( (pindex= komodo_chainactive(height-width+i+1)) != 0 )
851 {
852 if ( komodo_blockload(block,pindex) == 0 )
853 {
854 komodo_block2pubkey33(pubkey33,&block);
855 for (j=0; j<numnotaries; j++)
856 {
857 if ( memcmp(notarypubs33[j],pubkey33,33) == 0 )
858 {
859 minerids[nonz++] = j;
860 break;
861 }
862 }
0d8dc237 863 if ( j == numnotaries )
864 minerids[nonz++] = j;
df03549d 865 } else fprintf(stderr,"couldnt load block.%d\n",height);
866 }
867 }
868 return(nonz);
dbaf1154 869}
870
dac3c30c 871int32_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 872{
442215b4 873 int32_t i,j,notaryid=0,minerid,limit,nid; uint8_t destpubkey33[33];
dac3c30c 874 komodo_chosennotary(&notaryid,height,pubkey33,blocktimes[0]);
cb19d181 875 if ( height >= 82000 )
82f82d3f 876 {
442215b4 877 if ( notaryid >= 0 )
82f82d3f 878 {
879 for (i=1; i<66; i++)
880 {
442215b4 881 if ( mids[i] == notaryid )
82f82d3f 882 {
3c89a023 883 if ( height > 792000 )
0f5e787b 884 {
885 for (j=0; j<66; j++)
886 fprintf(stderr,"%d ",mids[j]);
887 fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i);
861119a1 888 return(-1);
0f5e787b 889 } else break;
82f82d3f 890 }
891 }
a658d926 892 if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 )
3ad8d247 893 {
26d9f4c3 894 if ( height > 807000 )
a658d926 895 return(-2);
fb64a588 896 }
897 return(1);
82f82d3f 898 } else return(0);
899 }
442215b4 900 else
4a4e912b 901 {
428a3934 902 if ( height >= 34000 && notaryid >= 0 )
4a4e912b 903 {
428a3934 904 if ( height < 79693 )
905 limit = 64;
906 else if ( height < 82000 )
907 limit = 8;
908 else limit = 66;
909 for (i=1; i<limit; i++)
66e3c532 910 {
70ebf02a 911 komodo_chosennotary(&nid,height-i,pubkey33,blocktimes[i]);
428a3934 912 if ( nid == notaryid )
913 {
79fb8179 914 //for (j=0; j<66; j++)
915 // fprintf(stderr,"%d ",mids[j]);
916 //fprintf(stderr,"ht.%d repeat mids[%d] nid.%d notaryid.%d\n",height-i,i,nid,notaryid);
428a3934 917 if ( height > 225000 )
918 return(-1);
919 }
66e3c532 920 }
428a3934 921 //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit);
922 return(1);
4a4e912b 923 }
4a4e912b 924 }
925 return(0);
926}
927
51dab149 928int32_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 929{
aa5ca001 930 int32_t depth,notarized_ht; uint256 MoM,kmdtxid;
51dab149 931 depth = komodo_MoMdata(&notarized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip);
0ab5b335 932 memset(MoMp,0,sizeof(*MoMp));
b3548b52 933 memset(kmdtxidp,0,sizeof(*kmdtxidp));
0ab5b335 934 *notarized_heightp = 0;
1b9f98cd 935 if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht )
0ab5b335 936 {
937 *MoMp = MoM;
938 *notarized_heightp = notarized_ht;
aa5ca001 939 *kmdtxidp = kmdtxid;
0ab5b335 940 }
941 return(depth);
942}
943
b62d7030 944int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
945{
c52074f2 946 int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex;
d82623d2 947 if ( (pindex= chainActive.Tip()) == 0 )
948 return(-1);
949 notarized_height = komodo_notarizeddata(pindex->nHeight,&notarized_hash,&notarized_desttxid);
b62d7030 950 *notarized_heightp = notarized_height;
aba9ea3c 951 if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
b62d7030 952 {
d82623d2 953 //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
b62d7030 954 if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
955 {
956 if ( nHeight < notarized_height )
957 {
2c5af2cd 958 //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
b62d7030 959 return(-1);
960 }
961 else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
962 {
beb911ec 963 fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
b62d7030 964 return(-1);
965 }
ccff4876 966 } //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 967 }
dc836ee4 968 //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 )
969 // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight);
b62d7030 970 return(0);
971}
485e48ca 972
83da1e16 973uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n)
c1c95e36 974{
975 LOCK(cs_main);
976 CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex;
63c93b0c 977 *txheighttimep = *txheightp = *tiptimep = 0;
978 *valuep = 0;
c1c95e36 979 if ( !GetTransaction(hash,tx,hashBlock,true) )
980 return(0);
981 uint32_t locktime = 0;
982 if ( n < tx.vout.size() )
983 {
c60397dd 984 if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
c1c95e36 985 {
986 *valuep = tx.vout[n].nValue;
987 *txheightp = pindex->nHeight;
83da1e16 988 *txheighttimep = pindex->nTime;
c60397dd 989 if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 )
990 *tiptimep = (uint32_t)tipindex->nTime;
c1c95e36 991 locktime = tx.nLockTime;
1f52f946 992 //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep);
c1c95e36 993 }
994 }
995 return(locktime);
996}
997
998uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
c60397dd 999
1000uint64_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 1001{
c60397dd 1002 uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex;
1003 if ( (pindex= chainActive[tipheight]) != 0 )
1004 tiptime = (uint32_t)pindex->nTime;
72070c94 1005 else fprintf(stderr,"cant find height[%d]\n",tipheight);
83da1e16 1006 if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 )
c1c95e36 1007 {
798f28c7 1008 if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) )
1009 return(komodo_interest(*txheightp,value,*locktimep,tiptime));
c1c95e36 1010 //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 1011 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);
1012 }
c1c95e36 1013 return(0);
1014}
8a7f7063 1015
1016int32_t komodo_isrealtime(int32_t *kmdheightp)
1017{
d82623d2 1018 struct komodo_state *sp; CBlockIndex *pindex;
8a7c9241 1019 if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 )
ffbc2f00 1020 *kmdheightp = sp->CURRENT_HEIGHT;
1021 else *kmdheightp = 0;
1b5b89ba 1022 if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() )
8a7f7063 1023 return(1);
1024 else return(0);
1025}
14aa6cc0 1026
99d7ed25 1027int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag)
14aa6cc0 1028{
14aa6cc0 1029 if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
1030 {
3d02f57b 1031 if ( txheight > 246748 )
14aa6cc0 1032 {
1033 if ( txheight < 247205 )
39d28b06 1034 cmptime -= 16000;
bd070d8b 1035 if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME )
14aa6cc0 1036 {
531b9293 1037 if ( tx.nLockTime != 1477258935 && dispflag != 0 )
14aa6cc0 1038 {
bd070d8b 1039 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 1040 }
1041 return(-1);
1042 }
948ad8f3 1043 if ( 0 && dispflag != 0 )
bd070d8b 1044 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 1045 }
14aa6cc0 1046 }
1047 return(0);
1048}
ec5ed2f7 1049
18443f69 1050/*
9464ac21 1051 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 1052
1053 komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass
1054
1055 commission must be in coinbase.vout[1] and must be >= 10000 sats
1056 PoS stake must be without txfee and in the last tx in the block at vout[0]
1057 PoW mining on PoS chain must solve a harder diff that adjusts, but never less than KOMODO_POWMINMULT
1058 */
1059#define KOMODO_POWMINMULT 16
1060
1061uint64_t komodo_commission(const CBlock *pblock)
1062{
1063 int32_t i,j,n=0,txn_count; uint64_t commission,total = 0;
1064 txn_count = pblock->vtx.size();
1065 for (i=0; i<txn_count; i++)
1066 {
3acce042 1067 n = pblock->vtx[i].vout.size();
18443f69 1068 for (j=0; j<n; j++)
1069 {
1070 //fprintf(stderr,"(%d %.8f).%d ",i,dstr(block.vtx[i].vout[j].nValue),j);
1071 if ( i != 0 || j != 1 )
1072 total += pblock->vtx[i].vout[j].nValue;
1073 }
1074 }
1075 //fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN));
1076 commission = ((total * ASSETCHAINS_COMMISSION) / COIN);
1077 if ( commission < 10000 )
1078 commission = 0;
1079 return(commission);
1080}
1081
acbc7a94 1082uint32_t komodo_segid32(char *coinaddr)
1083{
1084 bits256 addrhash;
3001f999 1085 vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr));
acbc7a94 1086 return(addrhash.uints[0]);
1087}
1088
049e24ce 1089int8_t komodo_segid(int32_t height)
1090{
86f88c4f 1091 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 1092 if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 )
1093 {
1094 if ( komodo_blockload(block,pindex) == 0 )
1095 {
86f88c4f 1096 txn_count = block.vtx.size();
1097 if ( txn_count > 1 && block.vtx[txn_count-1].vin.size() == 1 && block.vtx[txn_count-1].vout.size() == 1 )
049e24ce 1098 {
86f88c4f 1099 txid = block.vtx[txn_count-1].vin[0].prevout.hash;
1100 vout = block.vtx[txn_count-1].vin[0].prevout.n;
049e24ce 1101 txtime = komodo_txtime(&value,txid,vout,destaddr);
86f88c4f 1102 if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
049e24ce 1103 {
1104 strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
86f88c4f 1105 if ( strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value )
049e24ce 1106 {
1107 segid = komodo_segid32(voutaddr) & 0x3f;
1108 }
1109 } else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height);
1110 }
1111 }
1112 }
1113 return(segid);
1114}
1115
1116int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n)
1117{
1118 static uint8_t prevhashbuf[100]; static int32_t prevheight;
1119 int32_t i;
1120 if ( height == prevheight && n == 100 )
1121 memcpy(hashbuf,prevhashbuf,100);
1122 else
1123 {
1124 memset(hashbuf,0xff,n);
1125 for (i=0; i<n; i++)
1126 {
1127 hashbuf[i] = (uint8_t)komodo_segid(height+i);
bf915dce 1128 //fprintf(stderr,"%02x ",hashbuf[i]);
049e24ce 1129 }
1130 if ( n == 100 )
1131 {
1132 memcpy(prevhashbuf,hashbuf,100);
1133 prevheight = height;
bf915dce 1134 //fprintf(stderr,"segids.%d\n",height);
049e24ce 1135 }
1136 }
1137}
1138
1139uint32_t komodo_newstake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr)
1140{
4aef05c9 1141 CBlockIndex *pindex; bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval; uint256 hash,pasthash; int64_t diff=0; int32_t segid,minage,i,iter=0; uint32_t mfactor=64,txtime,winner = 0; arith_uint256 bnMaxPoSdiff; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN;
049e24ce 1142 txtime = komodo_txtime(&value,txid,vout,address);
89931e6e 1143 if ( validateflag == 0 && blocktime < GetAdjustedTime() )
f1d8e4b6 1144 blocktime = GetAdjustedTime();
4646f21b 1145 if ( nHeight < 6000 ) // POSTEST64
45ee62cb 1146 {
1147 if ( blocktime < prevtime+60 )
1148 blocktime = prevtime+60;
1149 }
de7cb53f 1150 else
1151 {
422b307c 1152 if ( blocktime < prevtime+3 )
1153 blocktime = prevtime+3;
de7cb53f 1154 }
049e24ce 1155 if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
1156 {
1157 //fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
1158 return(0);
1159 }
7ed0e00b 1160 if ( nHeight < 4400 ) // POSTEST64 change newstake to stake and stake to oldstake and remove
1161 bnTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
049e24ce 1162 mfactor = 1024;
1163 if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
1164 minage = 6000;
1165 pindex = 0;
1166 vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
1167 segid = ((nHeight + addrhash.uints[0]) & 0x3f);
1168 komodo_segids(hashbuf,nHeight-101,100);
1169 memcpy(&hashbuf[100],&addrhash,sizeof(addrhash));
1170 memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid));
1171 memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout));
1172 vcalc_sha256(0,(uint8_t *)&hash,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout));
1173 for (iter=0; iter<3600; iter++)
1174 {
1175 diff = (iter + blocktime - txtime - minage);
1176 if ( diff > 3600*24*30 )
1177 diff = 3600*24*30;
1178 if ( iter > 0 )
1179 diff += segid*2;
1180 if ( blocktime+iter+segid*2 < txtime+minage )
1181 continue;
1182 coinage = (value * diff) * ((diff >> 16) + 1);
1183 hashval = arith_uint256(supply * mfactor) * (UintToArith256(hash) / arith_uint256(coinage+1));
1184 if ( hashval <= bnTarget )
1185 {
1186 winner = 1;
1187 if ( validateflag == 0 )
1188 {
1189 blocktime += iter;
1190 blocktime += segid * 2;
1191 }
1192 break;
1193 }
1194 if ( validateflag != 0 )
1195 {
1196 /*for (i=31; i>=24; i--)
1197 fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
1198 fprintf(stderr," vs target ");
1199 for (i=31; i>=24; i--)
1200 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1201 fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d gap.%d %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,(int32_t)(blocktime - prevtime),dstr(value),(int32_t)diff);*/
1202 break;
1203 }
1204 }
1205 //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
1206 if ( 0 )
1207 {
1208 for (i=31; i>=24; i--)
1209 fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
1210 fprintf(stderr," vs ");
1211 for (i=31; i>=24; i--)
1212 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1213 fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,dstr(value),(int32_t)diff);
1214 }
1215 if ( nHeight < 10 )
1216 return(blocktime);
1217 return(blocktime * winner);
1218}
1219
18443f69 1220uint32_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)
1221{
049e24ce 1222 CBlockIndex *pindex; bool fNegative,fOverflow; uint8_t hashbuf[128]; char address[64]; bits256 addrhash; arith_uint256 hashval; uint256 hash,pasthash; int64_t diff=0; int32_t segid,minage,i,iter=0; uint32_t mfactor=64,txtime,winner = 0; arith_uint256 bnMaxPoSdiff; uint64_t value,coinage,supply = ASSETCHAINS_SUPPLY + nHeight*ASSETCHAINS_REWARD/SATOSHIDEN;
0cd39760 1223 if ( nHeight >= 4000 ) // POSTEST64 remove when this is oldstake
049e24ce 1224 return(komodo_newstake(validateflag,bnTarget,nHeight,txid,vout,blocktime,prevtime,destaddr));
18443f69 1225 txtime = komodo_txtime(&value,txid,vout,address);
bed8cd1f 1226 if ( blocktime < prevtime+57 )
1227 blocktime = prevtime+57;
7b6d6985 1228 if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
985990dd 1229 {
d6f8eeb9 1230 //fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
18443f69 1231 return(0);
985990dd 1232 }
d6f8eeb9 1233 if ( ASSETCHAINS_STAKED != 100 || nHeight < 2000 )
1234 {
1235 bnMaxPoSdiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
1236 bnMaxPoSdiff = (bnMaxPoSdiff / arith_uint256(4));
1237 if ( bnTarget < bnMaxPoSdiff )
1238 bnTarget = bnMaxPoSdiff;
1239 }
4c36b530 1240 if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
18443f69 1241 minage = 6000;
985990dd 1242 pindex = 0;
8154603b 1243 if ( (pindex= komodo_chainactive(nHeight>50?nHeight-50:1)) != 0 )
18443f69 1244 {
1245 vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
1246 segid = ((nHeight + addrhash.uints[0]) & 0x3f);
1247 pasthash = pindex->GetBlockHash();
1248 memcpy(hashbuf,&pasthash,sizeof(pasthash));
1249 memcpy(&hashbuf[sizeof(pasthash)],&addrhash,sizeof(addrhash));
d184dbb4 1250 if ( nHeight >= 2000 )
1251 {
1252 memcpy(&hashbuf[sizeof(pasthash)+sizeof(addrhash)],&txid,sizeof(txid));
1253 memcpy(&hashbuf[sizeof(pasthash)+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout));
1254 vcalc_sha256(0,(uint8_t *)&hash,hashbuf,(int32_t)sizeof(uint256)*3 + sizeof(vout));
1255 } else vcalc_sha256(0,(uint8_t *)&hash,hashbuf,(int32_t)sizeof(uint256)*2);
049e24ce 1256 vcalc_sha256(0,(uint8_t *)&hash,hashbuf,(int32_t)sizeof(uint256)*2);
18443f69 1257 //fprintf(stderr,"(%s) vs. (%s) %s %.8f txtime.%u\n",address,destaddr,hash.ToString().c_str(),dstr(value),txtime);
1258 for (iter=0; iter<3600; iter++)
1259 {
1260 diff = (iter + blocktime - txtime - minage);
049e24ce 1261 if ( diff > 3600*24*30 )
86f88c4f 1262 diff = 3600*24*30;
9b79591b 1263 if ( iter > 0 )
1264 diff += iter + segid*2;
26a2b5cd 1265 if ( blocktime+iter+segid*2 < txtime+minage )
1266 continue;
18443f69 1267 coinage = (value * diff) * ((diff >> 16) + 1);
049e24ce 1268 hashval = arith_uint256(supply * mfactor) * (UintToArith256(hash) / arith_uint256(coinage+1));
18443f69 1269 if ( hashval <= bnTarget )
1270 {
1271 winner = 1;
1272 if ( validateflag == 0 )
1273 {
1274 blocktime += iter;
1275 blocktime += segid * 2;
1276 }
1277 break;
1278 }
1279 if ( validateflag != 0 )
1280 {
db178ad2 1281 /*for (i=31; i>=24; i--)
18443f69 1282 fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
1283 fprintf(stderr," vs target ");
1284 for (i=31; i>=24; i--)
1285 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
db178ad2 1286 fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d gap.%d %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,(int32_t)(blocktime - prevtime),dstr(value),(int32_t)diff);*/
18443f69 1287 break;
1288 }
1289 }
1290 //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
1291 if ( 0 )
1292 {
1293 for (i=31; i>=24; i--)
1294 fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
1295 fprintf(stderr," vs ");
1296 for (i=31; i>=24; i--)
1297 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1298 fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u %.8f diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,dstr(value),(int32_t)diff);
1299 }
26a2b5cd 1300 } //else fprintf(stderr,"skip PoS scan: diff %d blocktime %u > %u txtime+minage %u pindex.%p\n",(int32_t)(blocktime - (txtime+minage)),blocktime,txtime,minage,pindex);
7e679101 1301 if ( nHeight < 10 )
18443f69 1302 return(blocktime);
1303 return(blocktime * winner);
1304}
1305
1306arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc)
1307{
1247b7d4 1308 CBlockIndex *pindex; arith_uint256 bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,ht,percPoS,diff,val;
18443f69 1309 *percPoSp = percPoS = 0;
8daf7caf 1310 if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) )
96df006a 1311 return(target);
18443f69 1312 sum = arith_uint256(0);
1313 ave = sum;
1314 for (i=n=0; i<100; i++)
1315 {
1316 ht = height - 100 + i;
e83bf6b3 1317 if ( ht <= 1 )
1318 continue;
18443f69 1319 if ( (pindex= komodo_chainactive(ht)) != 0 )
1320 {
1321 bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow);
1322 bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT));
1323 hashval = UintToArith256(pindex->GetBlockHash());
3753f568 1324 if ( hashval <= bnTarget ) // PoW is never as easy as PoS/16, some PoS will be counted as PoW
18443f69 1325 {
f2c1ac06 1326 if ( ASSETCHAINS_STAKED < 100 )
1327 fprintf(stderr,"1");
18443f69 1328 sum += hashval;
1329 n++;
689a24a7 1330 }
1331 else
1332 {
1333 percPoS++;
f2c1ac06 1334 if ( ASSETCHAINS_STAKED < 100 )
1335 fprintf(stderr,"0");
689a24a7 1336 }
f2c1ac06 1337 if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 )
f225a9ba 1338 fprintf(stderr," %d, ",percPoS);
18443f69 1339 }
1340 }
3753f568 1341 if ( n < 100 )
1342 percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
f2c1ac06 1343 if ( ASSETCHAINS_STAKED < 100 )
1344 fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height);
18443f69 1345 *percPoSp = percPoS;
1346 target = (target / arith_uint256(KOMODO_POWMINMULT));
1347 if ( n > 0 )
1348 {
1349 ave = (sum / arith_uint256(n));
1350 if ( ave > target )
1351 ave = target;
1352 } else return(target);
1353 if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
1354 {
181e67c6 1355 bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc);
f2c1ac06 1356 if ( ASSETCHAINS_STAKED < 100 )
18443f69 1357 {
1358 for (i=31; i>=24; i--)
1359 fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
1360 fprintf(stderr," increase diff -> ");
1361 for (i=31; i>=24; i--)
1362 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1363 fprintf(stderr," floor diff ");
1364 for (i=31; i>=24; i--)
1365 fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
1366 fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
1367 }
1368 }
1369 else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget
1370 {
1371 bnTarget = ((ave * arith_uint256(goalperc)) + (target * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
23b680a0 1372 if ( 1 )
18443f69 1373 {
1374 for (i=31; i>=24; i--)
1375 fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
1376 fprintf(stderr," decrease diff -> ");
1377 for (i=31; i>=24; i--)
1378 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1379 fprintf(stderr," floor diff ");
1380 for (i=31; i>=24; i--)
1381 fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
1382 fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
1383 }
1384 }
1385 else bnTarget = ave; // recent ave is perfect
1386 return(bnTarget);
1387}
1388
3acce042 1389int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget)
18443f69 1390{
2808b68f 1391 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 1392 if ( ASSETCHAINS_STAKED == 100 && height < 200 )
1393 return(1);
18443f69 1394 txn_count = pblock->vtx.size();
feefa2d3 1395 if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 )
18443f69 1396 {
1397 if ( prevtime == 0 )
1398 {
1399 if ( (previndex= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
1400 prevtime = (uint32_t)previndex->nTime;
1401 }
1402 txid = pblock->vtx[txn_count-1].vin[0].prevout.hash;
1403 vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
1404 if ( prevtime != 0 )
1405 {
1406 eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime,(char *)"");
1407 if ( eligible == 0 || eligible > pblock->nTime )
1408 {
e8dd12a1 1409 //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 1410 } else isPoS = 1;
1411 }
9c2f6f11 1412 if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx
18443f69 1413 {
1414 txtime = komodo_txtime(&value,txid,vout,destaddr);
1415 if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
1416 {
2808b68f 1417 strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
3acce042 1418 if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[txn_count-1].vout[0].nValue == value )
18443f69 1419 isPoS = 1; // close enough for a pre-filter
42c0fc6a 1420 //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 1421 } else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height);
764576d5 1422 } //else return(-1);
18443f69 1423 }
ffd6dd51 1424 //fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS);
18443f69 1425 return(isPoS);
1426}
1427
fb6bb4e8 1428int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
1429{
1430 int64_t checktoshis=0; uint8_t *script;
1431 if ( ASSETCHAINS_COMMISSION != 0 )
1432 {
1433 checktoshis = komodo_commission(pblock);
1434 if ( checktoshis > 10000 && pblock->vtx[0].vout.size() != 2 )
1435 return(-1);
1436 else if ( checktoshis != 0 )
1437 {
1438 script = (uint8_t *)pblock->vtx[0].vout[1].scriptPubKey.data();
1439 if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
1440 return(-1);
1441 if ( pblock->vtx[0].vout[1].nValue != checktoshis )
1442 {
1443 fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue));
1444 return(-1);
1445 }
1446 }
1447 }
1448 return(checktoshis);
1449}
1450
3fdb3782
SS
1451bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0;
1452
18443f69 1453int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
1454{
9464ac21 1455 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 1456 if ( !CheckEquihashSolution(pblock, Params()) )
1457 {
1458 fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height);
1459 return(-1);
1460 }
ec5b59fd 1461 hash = pblock->GetHash();
45ee62cb 1462 bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow);
9464ac21 1463 bhash = UintToArith256(hash);
1464 possible = komodo_block2pubkey33(pubkey33,pblock);
c685d692 1465 //fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget);
28b18b61 1466 if ( height == 0 )
f1b57a6e 1467 {
28b18b61 1468 if ( slowflag != 0 )
1469 return(0);
1470 if ( (pprev= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
1471 height = pprev->nHeight + 1;
1472 if ( height == 0 )
1473 return(0);
f1b57a6e 1474 }
2c089649 1475 if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget )
18443f69 1476 {
1477 failed = 1;
9464ac21 1478 if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case
18443f69 1479 {
1480 if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 )
1481 {
1482 for (i=0; i<n; i++)
1483 if ( memcmp(pubkey33,pubkeys[i],33) == 0 )
1484 {
1485 notaryid = i;
1486 break;
1487 }
1488 }
1489 }
9464ac21 1490 else if ( possible == 0 || ASSETCHAINS_SYMBOL[0] != 0 )
1491 {
f02af889 1492 if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW )
1493 return(0);
5aa69f6d 1494 //fprintf(stderr,"pow violation and no chance it is notary ht.%d %s\n",height,hash.ToString().c_str());
9464ac21 1495 return(-1);
1496 }
18443f69 1497 }
a3d08df0 1498 if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW
18443f69 1499 {
3acce042 1500 if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget)) == 0 )
18443f69 1501 {
f02af889 1502 if ( ASSETCHAINS_STAKED == 100 && height > 130 ) // only PoS allowed! POSTEST64
18443f69 1503 return(-1);
1504 else
1505 {
1506 if ( slowflag != 0 )
1507 bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
e83bf6b3 1508 else if ( height > 100 )
1509 bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT)); // lower bound
18443f69 1510 if ( bhash > bnTarget )
1511 {
1512 for (i=31; i>=16; i--)
2808b68f 1513 fprintf(stderr,"%02x",((uint8_t *)&bhash)[i]);
18443f69 1514 fprintf(stderr," > ");
1515 for (i=31; i>=16; i--)
1516 fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
1517 fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED);
1518 return(-1);
1519 }
1520 }
3acce042 1521 } else if ( is_PoSblock < 0 )
18443f69 1522 return(-1);
1523 }
d9f176ac 1524 if ( failed == 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
18443f69 1525 {
d9f176ac 1526 if ( height == 1 )
18443f69 1527 {
d9f176ac 1528 script = (uint8_t *)pblock->vtx[0].vout[0].scriptPubKey.data();
18443f69 1529 if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
1530 return(-1);
d9f176ac 1531 }
c9855c14 1532 else
1533 {
1534 if ( komodo_checkcommission(pblock,height) < 0 )
18443f69 1535 return(-1);
18443f69 1536 }
1537 }
c685d692 1538 //fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
1539 if ( failed != 0 && possible == 0 && notaryid < 0 )
18443f69 1540 return(-1);
1541 else return(0);
1542}
1543
This page took 0.545699 seconds and 4 git commands to generate.