]> Git Repo - VerusCoin.git/blame - src/komodo_bitcoind.h
test
[VerusCoin.git] / src / komodo_bitcoind.h
CommitLineData
d019c447 1/******************************************************************************
2 * Copyright © 2014-2016 The SuperNET Developers. *
3 * *
4 * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
5 * the top-level directory of this distribution for the individual copyright *
6 * holder information and the developer policies on copyright and licensing. *
7 * *
8 * Unless otherwise agreed in a custom licensing agreement, no part of the *
9 * SuperNET software, including this file may be copied, modified, propagated *
10 * or distributed except according to the terms contained in the LICENSE file *
11 * *
12 * Removal or modification of this copyright notice is prohibited. *
13 * *
14 ******************************************************************************/
15
3eea72f2 16// komodo functions that interact with bitcoind C++
17
9b0e1808 18#ifdef _WIN32
19#include <curl.h>
20#include <easy.h>
21#else
22#include <curl/curl.h>
23#include <curl/easy.h>
24#endif
25
26struct MemoryStruct { char *memory; size_t size; };
c2b50ce0 27struct return_string { char *ptr; size_t len; };
28
29// return data from the server
30#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
31#define CURL_GLOBAL_SSL (1<<0)
32#define CURL_GLOBAL_WIN32 (1<<1)
33
34
4ec67e74 35/************************************************************************
36 *
37 * Initialize the string handler so that it is thread safe
38 *
39 ************************************************************************/
40
41void init_string(struct return_string *s)
42{
43 s->len = 0;
44 s->ptr = (char *)calloc(1,s->len+1);
45 if ( s->ptr == NULL )
46 {
47 fprintf(stderr,"init_string malloc() failed\n");
48 exit(-1);
49 }
50 s->ptr[0] = '\0';
51}
c2b50ce0 52
4ec67e74 53/************************************************************************
54 *
55 * Use the "writer" to accumulate text until done
56 *
57 ************************************************************************/
58
59size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s)
60{
61 size_t new_len = s->len + size*nmemb;
62 s->ptr = (char *)realloc(s->ptr,new_len+1);
63 if ( s->ptr == NULL )
64 {
65 fprintf(stderr, "accumulate realloc() failed\n");
66 exit(-1);
67 }
68 memcpy(s->ptr+s->len,ptr,size*nmemb);
69 s->ptr[new_len] = '\0';
70 s->len = new_len;
71 return(size * nmemb);
72}
c2b50ce0 73
74/************************************************************************
75 *
76 * return the current system time in milliseconds
77 *
78 ************************************************************************/
79
80#define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field
81#ifdef EXTRACT_BITCOIND_RESULT
82
83/************************************************************************
84 *
85 * perform post processing of the results
86 *
87 ************************************************************************/
88
89char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params)
90{
91 long i,j,len; char *retstr = 0; cJSON *json,*result,*error;
92 //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
93 if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
94 {
95 if ( strcmp(command,"signrawtransaction") != 0 )
96 printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
97 return(rpcstr);
98 }
99 json = cJSON_Parse(rpcstr);
100 if ( json == 0 )
101 {
102 printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params);
103 free(rpcstr);
104 return(0);
105 }
106 result = cJSON_GetObjectItem(json,"result");
107 error = cJSON_GetObjectItem(json,"error");
108 if ( error != 0 && result != 0 )
109 {
110 if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL )
111 {
112 retstr = cJSON_Print(result);
113 len = strlen(retstr);
114 if ( retstr[0] == '"' && retstr[len-1] == '"' )
115 {
116 for (i=1,j=0; i<len-1; i++,j++)
117 retstr[j] = retstr[i];
118 retstr[j] = 0;
119 }
120 }
121 else if ( (error->type&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL )
122 {
123 if ( strcmp(command,"signrawtransaction") != 0 )
124 printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr);
125 }
126 free(rpcstr);
127 } else retstr = rpcstr;
128 free_json(json);
129 //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
130 return(retstr);
131}
132#endif
133
134/************************************************************************
135 *
136 * perform the query
137 *
138 ************************************************************************/
139
140
141char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params)
142{
143 static int didinit,count,count2; static double elapsedsum,elapsedsum2;
144 struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle;
145 char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
146 if ( didinit == 0 )
147 {
148 didinit = 1;
149 curl_global_init(CURL_GLOBAL_ALL); //init the curl session
150 }
151 numretries = 0;
152 if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 )
153 specialcase = 1;
154 else specialcase = 0;
155 if ( url[0] == 0 )
156 strcpy(url,"http://127.0.0.1:7876/nxt");
157 if ( specialcase != 0 && 0 )
158 printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params);
159try_again:
160 if ( retstrp != 0 )
161 *retstrp = 0;
162 starttime = OS_milliseconds();
163 curl_handle = curl_easy_init();
164 init_string(&s);
165 headers = curl_slist_append(0,"Expect:");
166
167 curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
168 curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
169 curl_easy_setopt(curl_handle,CURLOPT_URL, url);
4ec67e74 170 curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function
c2b50ce0 171 curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
172 curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
173 curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
174 if ( strncmp(url,"https",5) == 0 )
175 {
176 curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
177 curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
178 }
179 if ( userpass != 0 )
180 curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass);
181 databuf = 0;
182 if ( params != 0 )
183 {
184 if ( command != 0 && specialcase == 0 )
185 {
186 len = strlen(params);
187 if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) {
188 bracket0 = bracket1 = (char *)"";
189 }
190 else
191 {
192 bracket0 = (char *)"[";
193 bracket1 = (char *)"]";
194 }
195
196 databuf = (char *)malloc(256 + strlen(command) + strlen(params));
197 sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
198 //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
199 //
200 } //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
201 curl_easy_setopt(curl_handle,CURLOPT_POST,1L);
202 if ( databuf != 0 )
203 curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf);
204 else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params);
205 }
206 //laststart = milliseconds();
207 res = curl_easy_perform(curl_handle);
208 curl_slist_free_all(headers);
209 curl_easy_cleanup(curl_handle);
210 if ( databuf != 0 ) // clean up temporary buffer
211 {
212 free(databuf);
213 databuf = 0;
214 }
215 if ( res != CURLE_OK )
216 {
217 numretries++;
218 if ( specialcase != 0 )
219 {
220 printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
221 free(s.ptr);
222 return(0);
223 }
224 else if ( numretries >= 5 )
225 {
226 printf("Maximum number of retries exceeded!\n");
227 free(s.ptr);
228 return(0);
229 }
230 printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
231 free(s.ptr);
232 sleep((1<<numretries));
233 goto try_again;
234
235 }
236 else
237 {
238 if ( command != 0 && specialcase == 0 )
239 {
240 count++;
241 elapsedsum += (OS_milliseconds() - starttime);
242 if ( (count % 10000) == 0)
243 printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
244 if ( retstrp != 0 )
245 {
246 *retstrp = s.ptr;
247 return(s.ptr);
248 }
249 return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params));
250 }
251 else
252 {
253 if ( 0 && specialcase != 0 )
254 fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr);
255 count2++;
256 elapsedsum2 += (OS_milliseconds() - starttime);
257 if ( (count2 % 10000) == 0)
258 printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command);
259 return(s.ptr);
260 }
261 }
262 printf("bitcoind_RPC: impossible case\n");
263 free(s.ptr);
264 return(0);
265}
9b0e1808 266
267static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data)
268{
269 size_t realsize = (size * nmemb);
270 struct MemoryStruct *mem = (struct MemoryStruct *)data;
b858fa74 271 mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1));
9b0e1808 272 if ( mem->memory != 0 )
273 {
274 if ( ptr != 0 )
275 memcpy(&(mem->memory[mem->size]),ptr,realsize);
276 mem->size += realsize;
277 mem->memory[mem->size] = 0;
278 }
279 //printf("got %d bytes\n",(int32_t)(size*nmemb));
280 return(realsize);
281}
282
05d3d5ff 283char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3)
9b0e1808 284{
285 struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0;
286 if ( (cHandle= *cHandlep) == NULL )
287 *cHandlep = cHandle = curl_easy_init();
288 else curl_easy_reset(cHandle);
289 //#ifdef DEBUG
290 //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1);
291 //#endif
292 curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
293 curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0);
294 //curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1);
295 curl_easy_setopt(cHandle,CURLOPT_URL,url);
296 curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10);
297 if ( userpass != 0 && userpass[0] != 0 )
298 curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass);
299 if ( postfields != 0 && postfields[0] != 0 )
300 {
301 curl_easy_setopt(cHandle,CURLOPT_POST,1);
302 curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields);
303 }
304 if ( hdr0 != NULL && hdr0[0] != 0 )
305 {
306 //printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:"");
307 headers = curl_slist_append(headers,hdr0);
308 if ( hdr1 != 0 && hdr1[0] != 0 )
309 headers = curl_slist_append(headers,hdr1);
310 if ( hdr2 != 0 && hdr2[0] != 0 )
311 headers = curl_slist_append(headers,hdr2);
312 if ( hdr3 != 0 && hdr3[0] != 0 )
313 headers = curl_slist_append(headers,hdr3);
314 } //headers = curl_slist_append(0,"Expect:");
315 if ( headers != 0 )
316 curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers);
317 //res = curl_easy_perform(cHandle);
318 memset(&chunk,0,sizeof(chunk));
319 curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback);
320 curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk);
321 curl_easy_perform(cHandle);
322 curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code);
323 if ( headers != 0 )
324 curl_slist_free_all(headers);
325 if ( code != 200 )
326 printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory);
327 return(chunk.memory);
328}
329
3c0f5d94 330char *komodo_issuemethod(char *method,char *params,uint16_t port)
9b0e1808 331{
4ac6cd92 332 //static void *cHandle;
333 char url[512],*retstr=0,*retstr2,postdata[8192];
365378b5 334 if ( params == 0 || params[0] == 0 )
335 params = (char *)"[]";
9b0e1808 336 if ( strlen(params) < sizeof(postdata)-128 )
337 {
3c0f5d94 338 sprintf(url,(char *)"http://127.0.0.1:%u",port);
9b0e1808 339 sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
b05863f5 340 //printf("postdata.(%s) USERPASS.(%s)\n",postdata,USERPASS);
14871d49 341 retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,USERPASS,method,params);
c2b50ce0 342 //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0);
9b0e1808 343 }
1ccb1cf0 344 return(retstr2);
9b0e1808 345}
46ff7513 346//curl --url "http://127.0.0.1:13033" --user "user1557335368:pass111720054" --data "{\"method\":\"getinfo\",\"params\":[]}"
9b0e1808 347
3eea72f2 348uint32_t komodo_txtime(uint256 hash)
349{
350 CTransaction tx;
351 uint256 hashBlock;
7637aa7f 352 if (!GetTransaction(hash, tx,
353#ifndef KOMODO_ZCASH
354 Params().GetConsensus(),
355#endif
356 hashBlock, true))
3eea72f2 357 {
358 //printf("null GetTransaction\n");
359 return(tx.nLockTime);
360 }
361 return(0);
362}
363
364void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
365{
366 komodo_init();
367 //uint256 zero;
368 //printf("disconnect ht.%d\n",pindex->nHeight);
369 //memset(&zero,0,sizeof(zero));
370 //komodo_stateupdate(-pindex->nHeight,0,0,0,zero,0,0,0,0);
371}
372
373int32_t komodo_block2height(CBlock *block)
374{
189d9dee 375 int32_t i,n,height = 0; uint8_t *ptr;
3eea72f2 376 komodo_init();
189d9dee 377#ifdef KOMODO_ZCASH
378 ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
379#else
380 ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
381#endif
3eea72f2 382 if ( block->vtx[0].vin[0].scriptSig.size() > 5 )
383 {
384 //for (i=0; i<6; i++)
385 // printf("%02x",ptr[i]);
386 n = ptr[0];
387 for (i=0; i<n; i++)
388 {
389 //03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
390 height += ((uint32_t)ptr[i+1] << (i*8));
391 //printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
392 }
393 //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
394 }
395 return(height);
396}
397
398void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block)
399{
da00f2dd 400#ifdef KOMODO_ZCASH
484f8777 401 uint8_t *ptr = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data();
da00f2dd 402#else
403 uint8_t *ptr = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0];
404#endif
3eea72f2 405 komodo_init();
406 memcpy(pubkey33,ptr+1,33);
407}
408
409void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
410{
411 CBlock block;
412 komodo_init();
413 memset(pubkey33,0,33);
414 if ( pindex != 0 )
415 {
09019cdc 416 if ( ReadBlockFromDisk(block,(const CBlockIndex *)pindex
7637aa7f 417#ifndef KOMODO_ZCASH
09019cdc 418 ,Params().GetConsensus()
7637aa7f 419#endif
420 ) != 0 )
3eea72f2 421 {
422 komodo_block2pubkey33(pubkey33,block);
423 }
424 }
425 else
426 {
427 // height -> pubkey33
428 //printf("extending chaintip komodo_index2pubkey33 height.%d need to get pubkey33\n",height);
429 }
430}
431
b62d7030 432int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
433{
434 int32_t notarized_height; uint256 notarized_hash,notarized_desttxid; CBlockIndex *notary;
435 notarized_height = komodo_notarizeddata(chainActive.Tip()->nHeight,&notarized_hash,&notarized_desttxid);
436 *notarized_heightp = notarized_height;
d9d3a941 437 if ( notarized_height >= 0 && notarized_height <= chainActive.Tip()->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
b62d7030 438 {
439 //printf("nHeight.%d -> (%d %s)\n",chainActive.Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
440 if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
441 {
442 if ( nHeight < notarized_height )
443 {
444 fprintf(stderr,"nHeight.%d < NOTARIZED_HEIGHT.%d\n",nHeight,notarized_height);
445 return(-1);
446 }
447 else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
448 {
449 fprintf(stderr,"nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",nHeight,notarized_height);
450 return(-1);
451 }
452 } else fprintf(stderr,"unexpected error notary_hash %s ht.%d at ht.%d\n",notarized_hash.ToString().c_str(),notarized_height,notary->nHeight);
453 } else if ( notarized_height > 0 )
454 fprintf(stderr,"couldnt find notary_hash %s ht.%d\n",notarized_hash.ToString().c_str(),notarized_height);
455 return(0);
456}
This page took 0.079217 seconds and 4 git commands to generate.