]>
Commit | Line | Data |
---|---|---|
d019c447 | 1 | /****************************************************************************** |
37fed603 | 2 | * Copyright © 2014-2017 The SuperNET Developers. * |
d019c447 | 3 | * * |
4 | * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * | |
5 | * the top-level directory of this distribution for the individual copyright * | |
6 | * holder information and the developer policies on copyright and licensing. * | |
7 | * * | |
8 | * Unless otherwise agreed in a custom licensing agreement, no part of the * | |
9 | * SuperNET software, including this file may be copied, modified, propagated * | |
10 | * or distributed except according to the terms contained in the LICENSE file * | |
11 | * * | |
12 | * Removal or modification of this copyright notice is prohibited. * | |
13 | * * | |
14 | ******************************************************************************/ | |
15 | ||
3eea72f2 | 16 | // komodo functions that interact with bitcoind C++ |
17 | ||
9b0e1808 | 18 | #ifdef _WIN32 |
9d365796 | 19 | #include <curl/curl.h> |
20 | #include <curl/easy.h> | |
9b0e1808 | 21 | #else |
22 | #include <curl/curl.h> | |
23 | #include <curl/easy.h> | |
24 | #endif | |
25 | ||
5416af1d | 26 | #include "komodo_defs.h" |
27 | ||
36c733e9 | 28 | //#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) |
77be6cd9 | 29 | |
9b0e1808 | 30 | struct MemoryStruct { char *memory; size_t size; }; |
c2b50ce0 | 31 | struct return_string { char *ptr; size_t len; }; |
32 | ||
33 | // return data from the server | |
34 | #define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) | |
35 | #define CURL_GLOBAL_SSL (1<<0) | |
36 | #define CURL_GLOBAL_WIN32 (1<<1) | |
37 | ||
38 | ||
4ec67e74 | 39 | /************************************************************************ |
40 | * | |
41 | * Initialize the string handler so that it is thread safe | |
42 | * | |
43 | ************************************************************************/ | |
44 | ||
45 | void init_string(struct return_string *s) | |
46 | { | |
47 | s->len = 0; | |
48 | s->ptr = (char *)calloc(1,s->len+1); | |
49 | if ( s->ptr == NULL ) | |
50 | { | |
51 | fprintf(stderr,"init_string malloc() failed\n"); | |
52 | exit(-1); | |
53 | } | |
54 | s->ptr[0] = '\0'; | |
55 | } | |
c2b50ce0 | 56 | |
4ec67e74 | 57 | /************************************************************************ |
58 | * | |
59 | * Use the "writer" to accumulate text until done | |
60 | * | |
61 | ************************************************************************/ | |
62 | ||
63 | size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s) | |
64 | { | |
65 | size_t new_len = s->len + size*nmemb; | |
66 | s->ptr = (char *)realloc(s->ptr,new_len+1); | |
67 | if ( s->ptr == NULL ) | |
68 | { | |
69 | fprintf(stderr, "accumulate realloc() failed\n"); | |
70 | exit(-1); | |
71 | } | |
72 | memcpy(s->ptr+s->len,ptr,size*nmemb); | |
73 | s->ptr[new_len] = '\0'; | |
74 | s->len = new_len; | |
75 | return(size * nmemb); | |
76 | } | |
c2b50ce0 | 77 | |
78 | /************************************************************************ | |
79 | * | |
80 | * return the current system time in milliseconds | |
81 | * | |
82 | ************************************************************************/ | |
83 | ||
84 | #define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field | |
85 | #ifdef EXTRACT_BITCOIND_RESULT | |
86 | ||
87 | /************************************************************************ | |
88 | * | |
89 | * perform post processing of the results | |
90 | * | |
91 | ************************************************************************/ | |
92 | ||
93 | char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params) | |
94 | { | |
95 | long i,j,len; char *retstr = 0; cJSON *json,*result,*error; | |
96 | //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); | |
97 | if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 ) | |
98 | { | |
99 | if ( strcmp(command,"signrawtransaction") != 0 ) | |
100 | printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); | |
101 | return(rpcstr); | |
102 | } | |
103 | json = cJSON_Parse(rpcstr); | |
104 | if ( json == 0 ) | |
105 | { | |
106 | printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params); | |
107 | free(rpcstr); | |
108 | return(0); | |
109 | } | |
110 | result = cJSON_GetObjectItem(json,"result"); | |
111 | error = cJSON_GetObjectItem(json,"error"); | |
112 | if ( error != 0 && result != 0 ) | |
113 | { | |
114 | if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) | |
115 | { | |
116 | retstr = cJSON_Print(result); | |
117 | len = strlen(retstr); | |
118 | if ( retstr[0] == '"' && retstr[len-1] == '"' ) | |
119 | { | |
120 | for (i=1,j=0; i<len-1; i++,j++) | |
121 | retstr[j] = retstr[i]; | |
122 | retstr[j] = 0; | |
123 | } | |
124 | } | |
125 | else if ( (error->type&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL ) | |
126 | { | |
127 | if ( strcmp(command,"signrawtransaction") != 0 ) | |
128 | printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr); | |
129 | } | |
130 | free(rpcstr); | |
131 | } else retstr = rpcstr; | |
132 | free_json(json); | |
133 | //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); | |
134 | return(retstr); | |
135 | } | |
136 | #endif | |
137 | ||
138 | /************************************************************************ | |
139 | * | |
140 | * perform the query | |
141 | * | |
142 | ************************************************************************/ | |
143 | ||
c2b50ce0 | 144 | char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) |
145 | { | |
146 | static int didinit,count,count2; static double elapsedsum,elapsedsum2; | |
147 | struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; | |
148 | char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; | |
149 | if ( didinit == 0 ) | |
150 | { | |
151 | didinit = 1; | |
152 | curl_global_init(CURL_GLOBAL_ALL); //init the curl session | |
153 | } | |
154 | numretries = 0; | |
155 | if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 ) | |
156 | specialcase = 1; | |
157 | else specialcase = 0; | |
158 | if ( url[0] == 0 ) | |
159 | strcpy(url,"http://127.0.0.1:7876/nxt"); | |
160 | if ( specialcase != 0 && 0 ) | |
161 | printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); | |
162 | try_again: | |
163 | if ( retstrp != 0 ) | |
164 | *retstrp = 0; | |
165 | starttime = OS_milliseconds(); | |
166 | curl_handle = curl_easy_init(); | |
167 | init_string(&s); | |
168 | headers = curl_slist_append(0,"Expect:"); | |
9d365796 | 169 | |
c2b50ce0 | 170 | curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); |
171 | curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); | |
172 | curl_easy_setopt(curl_handle,CURLOPT_URL, url); | |
4ec67e74 | 173 | curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function |
c2b50ce0 | 174 | curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback |
175 | curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash | |
176 | curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback | |
177 | if ( strncmp(url,"https",5) == 0 ) | |
178 | { | |
179 | curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); | |
180 | curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0); | |
181 | } | |
182 | if ( userpass != 0 ) | |
183 | curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass); | |
184 | databuf = 0; | |
185 | if ( params != 0 ) | |
186 | { | |
187 | if ( command != 0 && specialcase == 0 ) | |
188 | { | |
189 | len = strlen(params); | |
190 | if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) { | |
191 | bracket0 = bracket1 = (char *)""; | |
192 | } | |
193 | else | |
194 | { | |
195 | bracket0 = (char *)"["; | |
196 | bracket1 = (char *)"]"; | |
197 | } | |
9d365796 | 198 | |
c2b50ce0 | 199 | databuf = (char *)malloc(256 + strlen(command) + strlen(params)); |
200 | sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); | |
05e307ec | 201 | //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf); |
c2b50ce0 | 202 | // |
203 | } //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params); | |
204 | curl_easy_setopt(curl_handle,CURLOPT_POST,1L); | |
205 | if ( databuf != 0 ) | |
206 | curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf); | |
207 | else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params); | |
208 | } | |
209 | //laststart = milliseconds(); | |
210 | res = curl_easy_perform(curl_handle); | |
211 | curl_slist_free_all(headers); | |
212 | curl_easy_cleanup(curl_handle); | |
213 | if ( databuf != 0 ) // clean up temporary buffer | |
214 | { | |
215 | free(databuf); | |
216 | databuf = 0; | |
217 | } | |
218 | if ( res != CURLE_OK ) | |
219 | { | |
220 | numretries++; | |
221 | if ( specialcase != 0 ) | |
222 | { | |
223 | printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); | |
224 | free(s.ptr); | |
225 | return(0); | |
226 | } | |
c59a3beb | 227 | else if ( numretries >= 1 ) |
c2b50ce0 | 228 | { |
bb7f7473 | 229 | //printf("Maximum number of retries exceeded!\n"); |
c2b50ce0 | 230 | free(s.ptr); |
231 | return(0); | |
232 | } | |
32323ea1 | 233 | if ( (rand() % 1000) == 0 ) |
234 | printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); | |
c2b50ce0 | 235 | free(s.ptr); |
236 | sleep((1<<numretries)); | |
237 | goto try_again; | |
9d365796 | 238 | |
c2b50ce0 | 239 | } |
240 | else | |
241 | { | |
242 | if ( command != 0 && specialcase == 0 ) | |
243 | { | |
244 | count++; | |
245 | elapsedsum += (OS_milliseconds() - starttime); | |
32323ea1 | 246 | if ( (count % 1000000) == 0) |
c2b50ce0 | 247 | printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url); |
248 | if ( retstrp != 0 ) | |
249 | { | |
250 | *retstrp = s.ptr; | |
251 | return(s.ptr); | |
252 | } | |
253 | return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params)); | |
254 | } | |
255 | else | |
256 | { | |
257 | if ( 0 && specialcase != 0 ) | |
258 | fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr); | |
259 | count2++; | |
260 | elapsedsum2 += (OS_milliseconds() - starttime); | |
261 | if ( (count2 % 10000) == 0) | |
262 | printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command); | |
263 | return(s.ptr); | |
264 | } | |
265 | } | |
266 | printf("bitcoind_RPC: impossible case\n"); | |
267 | free(s.ptr); | |
268 | return(0); | |
269 | } | |
9b0e1808 | 270 | |
271 | static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data) | |
272 | { | |
273 | size_t realsize = (size * nmemb); | |
274 | struct MemoryStruct *mem = (struct MemoryStruct *)data; | |
b858fa74 | 275 | mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1)); |
9b0e1808 | 276 | if ( mem->memory != 0 ) |
277 | { | |
278 | if ( ptr != 0 ) | |
279 | memcpy(&(mem->memory[mem->size]),ptr,realsize); | |
280 | mem->size += realsize; | |
281 | mem->memory[mem->size] = 0; | |
282 | } | |
283 | //printf("got %d bytes\n",(int32_t)(size*nmemb)); | |
284 | return(realsize); | |
285 | } | |
286 | ||
05d3d5ff | 287 | char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3) |
9b0e1808 | 288 | { |
289 | struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0; | |
290 | if ( (cHandle= *cHandlep) == NULL ) | |
291 | *cHandlep = cHandle = curl_easy_init(); | |
292 | else curl_easy_reset(cHandle); | |
293 | //#ifdef DEBUG | |
294 | //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1); | |
295 | //#endif | |
296 | curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); | |
297 | curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0); | |
298 | //curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1); | |
299 | curl_easy_setopt(cHandle,CURLOPT_URL,url); | |
300 | curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10); | |
301 | if ( userpass != 0 && userpass[0] != 0 ) | |
302 | curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass); | |
303 | if ( postfields != 0 && postfields[0] != 0 ) | |
304 | { | |
305 | curl_easy_setopt(cHandle,CURLOPT_POST,1); | |
306 | curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields); | |
307 | } | |
308 | if ( hdr0 != NULL && hdr0[0] != 0 ) | |
309 | { | |
310 | //printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:""); | |
311 | headers = curl_slist_append(headers,hdr0); | |
312 | if ( hdr1 != 0 && hdr1[0] != 0 ) | |
313 | headers = curl_slist_append(headers,hdr1); | |
314 | if ( hdr2 != 0 && hdr2[0] != 0 ) | |
315 | headers = curl_slist_append(headers,hdr2); | |
316 | if ( hdr3 != 0 && hdr3[0] != 0 ) | |
317 | headers = curl_slist_append(headers,hdr3); | |
318 | } //headers = curl_slist_append(0,"Expect:"); | |
319 | if ( headers != 0 ) | |
320 | curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers); | |
321 | //res = curl_easy_perform(cHandle); | |
322 | memset(&chunk,0,sizeof(chunk)); | |
323 | curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback); | |
324 | curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk); | |
325 | curl_easy_perform(cHandle); | |
326 | curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code); | |
327 | if ( headers != 0 ) | |
328 | curl_slist_free_all(headers); | |
329 | if ( code != 200 ) | |
330 | printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory); | |
331 | return(chunk.memory); | |
332 | } | |
333 | ||
0ded57c8 | 334 | char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) |
9b0e1808 | 335 | { |
4ac6cd92 | 336 | //static void *cHandle; |
a9132082 | 337 | char url[512],*retstr=0,*retstr2=0,postdata[8192]; |
365378b5 | 338 | if ( params == 0 || params[0] == 0 ) |
339 | params = (char *)"[]"; | |
9b0e1808 | 340 | if ( strlen(params) < sizeof(postdata)-128 ) |
341 | { | |
3c0f5d94 | 342 | sprintf(url,(char *)"http://127.0.0.1:%u",port); |
9b0e1808 | 343 | sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); |
05e307ec | 344 | //printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS); |
0ded57c8 | 345 | retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); |
c2b50ce0 | 346 | //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); |
9b0e1808 | 347 | } |
1ccb1cf0 | 348 | return(retstr2); |
9b0e1808 | 349 | } |
350 | ||
0cb025c1 | 351 | int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp) |
b000fa04 | 352 | { |
0cb025c1 | 353 | char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0; |
b000fa04 | 354 | params[0] = 0; |
355 | *kmdnotarized_heightp = 0; | |
0cb025c1 | 356 | if ( strcmp(dest,"KMD") == 0 ) |
b000fa04 | 357 | { |
05e307ec | 358 | port = KMD_PORT; |
0cb025c1 | 359 | userpass = KMDUSERPASS; |
360 | } | |
361 | else if ( strcmp(dest,"BTC") == 0 ) | |
362 | { | |
363 | port = 8332; | |
364 | userpass = BTCUSERPASS; | |
365 | } | |
366 | else return(0); | |
367 | if ( userpass[0] != 0 ) | |
368 | { | |
369 | if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 ) | |
b000fa04 | 370 | { |
70d83934 | 371 | //printf("(%s)\n",jsonstr); |
b000fa04 | 372 | if ( (json= cJSON_Parse(jsonstr)) != 0 ) |
373 | { | |
978ca795 | 374 | if ( (item= jobj(json,(char *)"result")) != 0 ) |
033f496d | 375 | { |
033f496d | 376 | height = jint(item,(char *)"blocks"); |
57dd4ada | 377 | *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height; |
033f496d | 378 | } |
b000fa04 | 379 | free_json(json); |
380 | } | |
381 | free(jsonstr); | |
382 | } | |
383 | sprintf(params,"[\"%s\", 1]",txidstr); | |
0cb025c1 | 384 | if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 ) |
b000fa04 | 385 | { |
70d83934 | 386 | //printf("(%s)\n",jsonstr); |
b000fa04 | 387 | if ( (json= cJSON_Parse(jsonstr)) != 0 ) |
388 | { | |
978ca795 | 389 | if ( (item= jobj(json,(char *)"result")) != 0 ) |
033f496d | 390 | { |
391 | txid_confirmations = jint(item,(char *)"confirmations"); | |
033f496d | 392 | if ( txid_confirmations > 0 && height > txid_confirmations ) |
393 | txid_height = height - txid_confirmations; | |
19857195 | 394 | else txid_height = height; |
094b401e | 395 | //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height); |
033f496d | 396 | } |
b000fa04 | 397 | free_json(json); |
398 | } | |
399 | free(jsonstr); | |
400 | } | |
43cc3df6 | 401 | } |
b000fa04 | 402 | return(txid_height); |
403 | } | |
404 | ||
20a5cb84 | 405 | int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH) |
b55c2367 | 406 | { |
407 | int32_t i; uint256 hash; char params[256]; | |
408 | for (i=0; i<32; i++) | |
ebd18944 | 409 | ((uint8_t *)&hash)[i] = script[2+i]; |
d56e5945 | 410 | if ( hash == NOTARIZED_HASH ) |
411 | return(0); | |
b556919a | 412 | for (i=0; i<32; i++) |
413 | printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]); | |
414 | printf(" notarized, "); | |
415 | for (i=0; i<32; i++) | |
416 | printf("%02x",((uint8_t *)&hash)[i]); | |
20a5cb84 | 417 | printf(" opreturn from [%s] ht.%d\n",ASSETCHAINS_SYMBOL,height); |
b556919a | 418 | return(-1); |
b55c2367 | 419 | } |
420 | ||
421 | int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) | |
422 | { | |
c3153900 | 423 | char params[256],*jsonstr,*hexstr; uint8_t script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; |
424 | /*params[0] = '['; | |
eee28662 | 425 | params[1] = '"'; |
426 | for (i=0; i<32; i++) | |
c3153900 | 427 | sprintf(¶ms[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]); |
428 | strcat(params,"\", 1]");*/ | |
429 | sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str()); | |
ed937645 | 430 | if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) |
431 | return(0); | |
05c1e522 | 432 | if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) |
a0b9382c | 433 | printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT); |
b55c2367 | 434 | if ( strcmp(dest,"KMD") == 0 ) |
b148643e | 435 | { |
436 | if ( KMDUSERPASS[0] != 0 ) | |
5201bb51 | 437 | { |
438 | if ( ASSETCHAINS_SYMBOL[0] != 0 ) | |
a0b9382c | 439 | { |
05e307ec | 440 | jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); |
21abd4df | 441 | //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr); |
a0b9382c | 442 | } |
443 | }//else jsonstr = _dex_getrawtransaction(); | |
48d0e5df | 444 | else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok |
b148643e | 445 | } |
b55c2367 | 446 | else if ( strcmp(dest,"BTC") == 0 ) |
b148643e | 447 | { |
448 | if ( BTCUSERPASS[0] != 0 ) | |
48d0e5df | 449 | { |
eee28662 | 450 | //printf("BTCUSERPASS.(%s)\n",BTCUSERPASS); |
b148643e | 451 | jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,8332); |
48d0e5df | 452 | } |
b148643e | 453 | //else jsonstr = _dex_getrawtransaction(); |
48d0e5df | 454 | else return(0); |
b148643e | 455 | } |
9674c671 | 456 | else |
457 | { | |
458 | printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest); | |
459 | return(-1); | |
460 | } | |
b55c2367 | 461 | if ( jsonstr != 0 ) |
462 | { | |
13b64fd6 | 463 | if ( (json= cJSON_Parse(jsonstr)) != 0 ) |
b55c2367 | 464 | { |
fa73aa67 | 465 | if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 ) |
b55c2367 | 466 | { |
467 | vout = jitem(vouts,n-1); | |
34c68daa | 468 | if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) |
a0b9382c | 469 | printf("vout.(%s)\n",jprint(vout,0)); |
523a5dc7 | 470 | if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 ) |
b55c2367 | 471 | { |
523a5dc7 | 472 | if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) |
b55c2367 | 473 | { |
e35bc6fe | 474 | printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str()); |
b55c2367 | 475 | len = strlen(hexstr) >> 1; |
476 | decode_hex(script,len,hexstr); | |
279fac91 | 477 | if ( script[1] == 0x4c ) |
478 | { | |
479 | script++; | |
480 | len--; | |
481 | } | |
482 | else if ( script[1] == 0x4d ) | |
483 | { | |
484 | script += 2; | |
485 | len -= 2; | |
486 | } | |
20a5cb84 | 487 | retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH); |
b55c2367 | 488 | } |
489 | } | |
490 | } | |
491 | free_json(txjson); | |
492 | } | |
493 | free(jsonstr); | |
494 | } | |
495 | return(retval); | |
496 | } | |
497 | ||
2934460c | 498 | /*uint256 komodo_getblockhash(int32_t height) |
23256cca | 499 | { |
dffceecf | 500 | uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32]; |
23256cca | 501 | memset(&hash,0,sizeof(hash)); |
502 | sprintf(params,"[%d]",height); | |
34017212 | 503 | if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_PORT)) != 0 ) |
23256cca | 504 | { |
ccf895cf | 505 | if ( (result= cJSON_Parse(jsonstr)) != 0 ) |
506 | { | |
25391719 | 507 | if ( (hexstr= jstr(result,(char *)"result")) != 0 ) |
ccf895cf | 508 | { |
509 | if ( is_hexstr(hexstr,0) == 64 ) | |
e9f49d50 | 510 | { |
511 | decode_hex(revbuf,32,hexstr); | |
512 | for (i=0; i<32; i++) | |
513 | ((uint8_t *)&hash)[i] = revbuf[31-i]; | |
514 | } | |
ccf895cf | 515 | } |
516 | free_json(result); | |
517 | } | |
5f1f19fd | 518 | printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash); |
1fd57718 | 519 | free(jsonstr); |
23256cca | 520 | } |
521 | return(hash); | |
522 | } | |
523 | ||
2934460c | 524 | uint256 _komodo_getblockhash(int32_t height);*/ |
6b0e06b5 | 525 | |
23256cca | 526 | uint64_t komodo_seed(int32_t height) |
527 | { | |
39b462c7 | 528 | uint64_t seed = 0; |
2934460c | 529 | /*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds... |
8aef9e40 | 530 | { |
39b462c7 | 531 | uint256 hash,zero; CBlockIndex *pindex; |
8aef9e40 | 532 | memset(&hash,0,sizeof(hash)); |
533 | memset(&zero,0,sizeof(zero)); | |
534 | if ( height > 10 ) | |
535 | height -= 10; | |
536 | if ( ASSETCHAINS_SYMBOL[0] == 0 ) | |
537 | hash = _komodo_getblockhash(height); | |
538 | if ( memcmp(&hash,&zero,sizeof(hash)) == 0 ) | |
539 | hash = komodo_getblockhash(height); | |
540 | int32_t i; | |
541 | for (i=0; i<32; i++) | |
542 | printf("%02x",((uint8_t *)&hash)[i]); | |
543 | printf(" seed.%d\n",height); | |
8c072b0b | 544 | seed = arith_uint256(hash.GetHex()).GetLow64(); |
8aef9e40 | 545 | } |
2934460c | 546 | else*/ |
8aef9e40 | 547 | { |
93fb251c | 548 | seed = (height << 13) ^ (height << 2); |
549 | seed <<= 21; | |
8aef9e40 | 550 | seed |= (height & 0xffffffff); |
93fb251c | 551 | seed ^= (seed << 17) ^ (seed << 1); |
8aef9e40 | 552 | } |
23256cca | 553 | return(seed); |
554 | } | |
555 | ||
3eea72f2 | 556 | uint32_t komodo_txtime(uint256 hash) |
557 | { | |
558 | CTransaction tx; | |
559 | uint256 hashBlock; | |
7637aa7f | 560 | if (!GetTransaction(hash, tx, |
561 | #ifndef KOMODO_ZCASH | |
562 | Params().GetConsensus(), | |
563 | #endif | |
564 | hashBlock, true)) | |
3eea72f2 | 565 | { |
566 | //printf("null GetTransaction\n"); | |
567 | return(tx.nLockTime); | |
568 | } | |
569 | return(0); | |
570 | } | |
571 | ||
572 | void komodo_disconnect(CBlockIndex *pindex,CBlock& block) | |
573 | { | |
7c130297 | 574 | char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; |
e0440cc3 | 575 | //fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight); |
c93dc546 | 576 | komodo_init(pindex->nHeight); |
f3a1de3a | 577 | if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) |
7a183152 | 578 | { |
9c432d66 | 579 | //sp->rewinding = pindex->nHeight; |
580 | //fprintf(stderr,"-%d ",pindex->nHeight); | |
7a183152 | 581 | } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL); |
3eea72f2 | 582 | } |
583 | ||
303fbd20 | 584 | |
f24b36ca | 585 | int32_t komodo_is_notarytx(const CTransaction& tx) |
586 | { | |
587 | uint8_t *ptr,crypto777[33]; | |
0554de3c | 588 | if ( tx.vout.size() > 0 ) |
589 | { | |
f24b36ca | 590 | #ifdef KOMODO_ZCASH |
0554de3c | 591 | ptr = (uint8_t *)tx.vout[0].scriptPubKey.data(); |
f24b36ca | 592 | #else |
0554de3c | 593 | ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0]; |
f24b36ca | 594 | #endif |
0554de3c | 595 | if ( ptr != 0 ) |
303fbd20 | 596 | { |
0554de3c | 597 | decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); |
598 | if ( memcmp(ptr+1,crypto777,33) == 0 ) | |
599 | { | |
600 | //printf("found notarytx\n"); | |
601 | return(1); | |
602 | } | |
303fbd20 | 603 | } |
f24b36ca | 604 | } |
303fbd20 | 605 | return(0); |
f24b36ca | 606 | } |
607 | ||
3eea72f2 | 608 | int32_t komodo_block2height(CBlock *block) |
609 | { | |
189d9dee | 610 | int32_t i,n,height = 0; uint8_t *ptr; |
0554de3c | 611 | if ( block->vtx[0].vin.size() > 0 ) |
612 | { | |
189d9dee | 613 | #ifdef KOMODO_ZCASH |
0554de3c | 614 | ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data(); |
189d9dee | 615 | #else |
0554de3c | 616 | ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0]; |
189d9dee | 617 | #endif |
0554de3c | 618 | if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 ) |
3eea72f2 | 619 | { |
0554de3c | 620 | //for (i=0; i<6; i++) |
621 | // printf("%02x",ptr[i]); | |
622 | n = ptr[0]; | |
623 | for (i=0; i<n; i++) | |
624 | { | |
625 | //03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256 | |
626 | height += ((uint32_t)ptr[i+1] << (i*8)); | |
627 | //printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height); | |
628 | } | |
629 | //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height); | |
3eea72f2 | 630 | } |
0554de3c | 631 | //komodo_init(height); |
3eea72f2 | 632 | } |
633 | return(height); | |
634 | } | |
635 | ||
636 | void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block) | |
637 | { | |
2dbf06e8 | 638 | int32_t n; |
0554de3c | 639 | memset(pubkey33,0,33); |
97561034 | 640 | if ( block.vtx[0].vout.size() > 0 ) |
0554de3c | 641 | { |
da00f2dd | 642 | #ifdef KOMODO_ZCASH |
0554de3c | 643 | uint8_t *ptr = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data(); |
da00f2dd | 644 | #else |
0554de3c | 645 | uint8_t *ptr = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; |
da00f2dd | 646 | #endif |
0554de3c | 647 | //komodo_init(0); |
648 | n = block.vtx[0].vout[0].scriptPubKey.size(); | |
649 | if ( n == 35 ) | |
650 | memcpy(pubkey33,ptr+1,33); | |
651 | } | |
3eea72f2 | 652 | } |
653 | ||
d7093b33 | 654 | int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) |
875cf683 | 655 | { |
656 | block.SetNull(); | |
657 | // Open history file to read | |
658 | CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION); | |
659 | if (filein.IsNull()) | |
660 | return(-1); | |
661 | // Read block | |
662 | try { filein >> block; } | |
663 | catch (const std::exception& e) | |
664 | { | |
665 | fprintf(stderr,"readblockfromdisk err B\n"); | |
666 | return(-1); | |
667 | } | |
668 | return(0); | |
669 | } | |
670 | ||
ae0bb3d3 | 671 | uint32_t komodo_chainactive_timestamp() |
672 | { | |
673 | if ( chainActive.Tip() != 0 ) | |
674 | return((uint32_t)chainActive.Tip()->GetBlockTime()); | |
e34a9d43 | 675 | else return(0); |
ae0bb3d3 | 676 | } |
677 | ||
7d44d3dd | 678 | CBlockIndex *komodo_chainactive(int32_t height) |
679 | { | |
5150cb47 | 680 | if ( chainActive.Tip() != 0 ) |
7d44d3dd | 681 | { |
5150cb47 | 682 | if ( height <= chainActive.Tip()->nHeight ) |
683 | return(chainActive[height]); | |
129d39b0 | 684 | // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight); |
d54aa57d | 685 | } |
8c8a07ce | 686 | //fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height); |
d54aa57d | 687 | return(0); |
7d44d3dd | 688 | } |
689 | ||
690 | uint32_t komodo_heightstamp(int32_t height) | |
691 | { | |
0cb1d2da | 692 | CBlockIndex *ptr; |
58bec1f9 | 693 | if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) |
f21afd94 | 694 | return(ptr->nTime); |
0cb1d2da | 695 | else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height); |
7d44d3dd | 696 | return(0); |
697 | } | |
698 | ||
3eea72f2 | 699 | void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) |
700 | { | |
701 | CBlock block; | |
bc9f2e03 | 702 | //komodo_init(height); |
3eea72f2 | 703 | memset(pubkey33,0,33); |
704 | if ( pindex != 0 ) | |
705 | { | |
a92123ef | 706 | if ( komodo_blockload(block,pindex) == 0 ) |
707 | komodo_block2pubkey33(pubkey33,block); | |
3eea72f2 | 708 | } |
709 | else | |
710 | { | |
711 | // height -> pubkey33 | |
712 | //printf("extending chaintip komodo_index2pubkey33 height.%d need to get pubkey33\n",height); | |
713 | } | |
714 | } | |
715 | ||
875cf683 | 716 | void komodo_connectpindex(CBlockIndex *pindex) |
717 | { | |
718 | CBlock block; | |
a92123ef | 719 | if ( komodo_blockload(block,pindex) == 0 ) |
720 | komodo_connectblock(pindex,block); | |
875cf683 | 721 | } |
722 | ||
85ef725a | 723 | int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); |
8eaa7b03 | 724 | int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); |
6034c671 | 725 | |
c142de7e | 726 | int8_t komodo_minerid(int32_t height,uint8_t *pubkey33) |
4a4e912b | 727 | { |
8eaa7b03 | 728 | int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t _pubkey33[33],pubkeys[64][33]; |
a8e94add | 729 | if ( pubkey33 == 0 && (pindex= chainActive[height]) != 0 ) |
fc318ffe | 730 | { |
85ef725a | 731 | timestamp = pindex->GetBlockTime(); |
c142de7e | 732 | if ( pubkey33 == 0 ) |
733 | { | |
734 | pubkey33 = _pubkey33; | |
735 | komodo_index2pubkey33(pubkey33,pindex,height); | |
736 | } | |
85ef725a | 737 | if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 ) |
e9ed4986 | 738 | { |
18594cf7 | 739 | for (i=0; i<num; i++) |
740 | if ( memcmp(pubkeys[i],pubkey33,33) == 0 ) | |
741 | return(i); | |
fc318ffe | 742 | } |
dac1ef88 | 743 | } |
8eaa7b03 | 744 | return(komodo_electednotary(&numnotaries,pubkey33,height,timestamp)); |
4a4e912b | 745 | } |
746 | ||
8c654ec5 | 747 | int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,int32_t *nonzpkeysp,int32_t height) |
353af8aa | 748 | { |
dac1ef88 | 749 | int32_t i,j,duplicate; CBlockIndex *pindex; uint8_t pubkey33[33]; |
353af8aa | 750 | memset(mids,-1,sizeof(*mids)*66); |
751 | for (i=duplicate=0; i<66; i++) | |
752 | { | |
3c525df1 | 753 | if ( (pindex= komodo_chainactive(height-i)) != 0 ) |
353af8aa | 754 | { |
755 | komodo_index2pubkey33(pubkey33,pindex,height-i); | |
8c654ec5 | 756 | for (j=0; j<33; j++) |
757 | pubkeys[i][j] = pubkey33[j]; | |
17c303dd | 758 | if ( (mids[i]= komodo_minerid(height-i,pubkey33)) >= 0 ) |
759 | { | |
611acf22 | 760 | //mids[i] = *(int32_t *)pubkey33; |
353af8aa | 761 | (*nonzpkeysp)++; |
17c303dd | 762 | } |
353af8aa | 763 | if ( mids[0] >= 0 && i > 0 && mids[i] == mids[0] ) |
764 | duplicate++; | |
3c525df1 | 765 | } |
353af8aa | 766 | } |
f2805ceb | 767 | if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) ) |
353af8aa | 768 | return(1); |
769 | else return(0); | |
770 | } | |
771 | ||
780c9ff1 | 772 | int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) |
dbaf1154 | 773 | { |
774 | int32_t i,n=0; | |
780c9ff1 | 775 | for (i=0; i<width; i++,n++) |
056447a6 | 776 | { |
777 | if ( height-i <= 0 ) | |
778 | break; | |
c142de7e | 779 | minerids[i] = komodo_minerid(height - i,0); |
056447a6 | 780 | } |
dbaf1154 | 781 | return(n); |
782 | } | |
783 | ||
8683bd8d | 784 | int32_t komodo_is_special(int32_t height,uint8_t pubkey33[33],uint32_t timestamp) |
4a4e912b | 785 | { |
dae6126c | 786 | int32_t i,notaryid=0,minerid,limit,nid; uint8_t _pubkey33[33]; |
787 | if ( height >= 225000 ) | |
8683bd8d | 788 | komodo_chosennotary(¬aryid,height,_pubkey33,timestamp); |
4a4e912b | 789 | if ( height >= 34000 && notaryid >= 0 ) |
790 | { | |
031b1129 | 791 | if ( height < 79693 ) |
792 | limit = 64; | |
793 | else if ( height < 82000 ) | |
3fe63a7d | 794 | limit = 8; |
28bc6208 | 795 | else limit = 66; |
1b3ce02c | 796 | for (i=1; i<limit; i++) |
4a4e912b | 797 | { |
8683bd8d | 798 | komodo_chosennotary(&nid,height-i,_pubkey33,timestamp); |
8c072c2d | 799 | if ( nid == notaryid ) //komodo_minerid(height-i,_pubkey33) |
66e3c532 | 800 | { |
86ad1cb1 | 801 | if ( (0) && notaryid > 0 ) |
dae6126c | 802 | fprintf(stderr,"ht.%d notaryid.%d already mined -i.%d nid.%d\n",height,notaryid,i,nid); |
803 | if ( height > 225000 ) | |
804 | return(-1); | |
66e3c532 | 805 | } |
4a4e912b | 806 | } |
6a645f7b | 807 | //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit); |
4a4e912b | 808 | return(1); |
809 | } | |
810 | return(0); | |
811 | } | |
812 | ||
b62d7030 | 813 | int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash) |
814 | { | |
d82623d2 | 815 | int32_t notarized_height; uint256 notarized_hash,notarized_desttxid; CBlockIndex *notary; CBlockIndex *pindex; |
816 | if ( (pindex= chainActive.Tip()) == 0 ) | |
817 | return(-1); | |
818 | notarized_height = komodo_notarizeddata(pindex->nHeight,¬arized_hash,¬arized_desttxid); | |
b62d7030 | 819 | *notarized_heightp = notarized_height; |
aba9ea3c | 820 | if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 ) |
b62d7030 | 821 | { |
d82623d2 | 822 | //printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str()); |
b62d7030 | 823 | if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg |
824 | { | |
825 | if ( nHeight < notarized_height ) | |
826 | { | |
2c5af2cd | 827 | //fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); |
b62d7030 | 828 | return(-1); |
829 | } | |
830 | else if ( nHeight == notarized_height && memcmp(&hash,¬arized_hash,sizeof(hash)) != 0 ) | |
831 | { | |
beb911ec | 832 | fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); |
b62d7030 | 833 | return(-1); |
834 | } | |
beb911ec | 835 | } else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->nHeight); |
836 | } | |
837 | else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 ) | |
d82623d2 | 838 | fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight); |
b62d7030 | 839 | return(0); |
840 | } | |
485e48ca | 841 | |
83da1e16 | 842 | uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) |
c1c95e36 | 843 | { |
844 | LOCK(cs_main); | |
845 | CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; | |
63c93b0c | 846 | *txheighttimep = *txheightp = *tiptimep = 0; |
847 | *valuep = 0; | |
c1c95e36 | 848 | if ( !GetTransaction(hash,tx,hashBlock,true) ) |
849 | return(0); | |
850 | uint32_t locktime = 0; | |
851 | if ( n < tx.vout.size() ) | |
852 | { | |
853 | if ( (pindex= mapBlockIndex[hashBlock]) != 0 && (tipindex= chainActive.Tip()) != 0 ) | |
854 | { | |
855 | *valuep = tx.vout[n].nValue; | |
856 | *txheightp = pindex->nHeight; | |
83da1e16 | 857 | *txheighttimep = pindex->nTime; |
c1c95e36 | 858 | *tiptimep = tipindex->nTime; |
859 | locktime = tx.nLockTime; | |
1f52f946 | 860 | //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); |
c1c95e36 | 861 | } |
862 | } | |
863 | return(locktime); | |
864 | } | |
865 | ||
866 | uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); | |
798f28c7 | 867 | uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue) |
c1c95e36 | 868 | { |
83da1e16 | 869 | uint64_t value; uint32_t tiptime,txheighttimep; |
870 | if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 ) | |
c1c95e36 | 871 | { |
798f28c7 | 872 | if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) |
873 | return(komodo_interest(*txheightp,value,*locktimep,tiptime)); | |
c1c95e36 | 874 | //fprintf(stderr,"nValue %llu lock.%u:%u nTime.%u -> %llu\n",(long long)coins.vout[n].nValue,coins.nLockTime,timestamp,pindex->nTime,(long long)interest); |
1c2f0c49 | 875 | else fprintf(stderr,"komodo_accrued_interest value mismatch %llu vs %llu or height mismatch %d vs %d\n",(long long)value,(long long)checkvalue,*txheightp,checkheight); |
876 | } | |
c1c95e36 | 877 | return(0); |
878 | } | |
8a7f7063 | 879 | |
880 | int32_t komodo_isrealtime(int32_t *kmdheightp) | |
881 | { | |
d82623d2 | 882 | struct komodo_state *sp; CBlockIndex *pindex; |
8a7c9241 | 883 | if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) |
ffbc2f00 | 884 | *kmdheightp = sp->CURRENT_HEIGHT; |
885 | else *kmdheightp = 0; | |
1b5b89ba | 886 | if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() ) |
8a7f7063 | 887 | return(1); |
888 | else return(0); | |
889 | } | |
14aa6cc0 | 890 | |
3bc88f14 | 891 | int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag) |
14aa6cc0 | 892 | { |
893 | uint32_t cmptime = nTime; | |
894 | if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) | |
895 | { | |
3d02f57b | 896 | if ( txheight > 246748 ) |
14aa6cc0 | 897 | { |
898 | if ( txheight < 247205 ) | |
39d28b06 | 899 | cmptime -= 16000; |
14aa6cc0 | 900 | if ( (int64_t)tx.nLockTime < cmptime-3600 ) |
901 | { | |
bbaa0f9d | 902 | if ( tx.nLockTime != 1477258935 || dispflag != 0 ) |
14aa6cc0 | 903 | { |
66294e69 | 904 | //fprintf(stderr,"komodo_validate_interest.%d reject.%d [%d] locktime %u cmp2.%u\n",dispflag,txheight,(int32_t)(tx.nLockTime - (cmptime-3600)),(uint32_t)tx.nLockTime,cmptime); |
14aa6cc0 | 905 | } |
906 | return(-1); | |
907 | } | |
948ad8f3 | 908 | if ( 0 && dispflag != 0 ) |
3bc88f14 | 909 | fprintf(stderr,"validateinterest.%d accept.%d [%d] locktime %u cmp2.%u\n",dispflag,(int32_t)txheight,(int32_t)(tx.nLockTime - (cmptime-3600)),(int32_t)tx.nLockTime,cmptime); |
14aa6cc0 | 910 | } |
14aa6cc0 | 911 | } |
912 | return(0); | |
913 | } |