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