Hush Full Node software. We were censored from Github, this is where all development happens now. https://hush.is
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1535 lines
59 KiB

8 years ago
/******************************************************************************
* Copyright © 2014-2018 The SuperNET Developers. *
8 years ago
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
8 years ago
// komodo functions that interact with bitcoind C++
8 years ago
#ifdef _WIN32
7 years ago
#include <curl/curl.h>
#include <curl/easy.h>
8 years ago
#else
#include <curl/curl.h>
#include <curl/easy.h>
#endif
7 years ago
#include "komodo_defs.h"
6 years ago
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp);
7 years ago
//#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr))
8 years ago
8 years ago
struct MemoryStruct { char *memory; size_t size; };
8 years ago
struct return_string { char *ptr; size_t len; };
// return data from the server
#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
#define CURL_GLOBAL_SSL (1<<0)
#define CURL_GLOBAL_WIN32 (1<<1)
8 years ago
/************************************************************************
*
* Initialize the string handler so that it is thread safe
*
************************************************************************/
void init_string(struct return_string *s)
{
s->len = 0;
s->ptr = (char *)calloc(1,s->len+1);
if ( s->ptr == NULL )
{
fprintf(stderr,"init_string malloc() failed\n");
exit(-1);
}
s->ptr[0] = '\0';
}
8 years ago
8 years ago
/************************************************************************
*
* Use the "writer" to accumulate text until done
*
************************************************************************/
size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = (char *)realloc(s->ptr,new_len+1);
if ( s->ptr == NULL )
{
fprintf(stderr, "accumulate realloc() failed\n");
exit(-1);
}
memcpy(s->ptr+s->len,ptr,size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return(size * nmemb);
}
8 years ago
/************************************************************************
*
* return the current system time in milliseconds
*
************************************************************************/
#define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field
#ifdef EXTRACT_BITCOIND_RESULT
/************************************************************************
*
* perform post processing of the results
*
************************************************************************/
char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params)
{
long i,j,len; char *retstr = 0; cJSON *json,*result,*error;
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
{
if ( strcmp(command,"signrawtransaction") != 0 )
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
return(rpcstr);
}
json = cJSON_Parse(rpcstr);
if ( json == 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params);
free(rpcstr);
return(0);
}
result = cJSON_GetObjectItem(json,"result");
error = cJSON_GetObjectItem(json,"error");
if ( error != 0 && result != 0 )
{
if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL )
{
retstr = cJSON_Print(result);
len = strlen(retstr);
if ( retstr[0] == '"' && retstr[len-1] == '"' )
{
for (i=1,j=0; i<len-1; i++,j++)
retstr[j] = retstr[i];
retstr[j] = 0;
}
}
else if ( (error->type&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL )
{
if ( strcmp(command,"signrawtransaction") != 0 )
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr);
}
free(rpcstr);
} else retstr = rpcstr;
free_json(json);
//fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
return(retstr);
}
#endif
/************************************************************************
*
* perform the query
*
************************************************************************/
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params)
{
static int didinit,count,count2; static double elapsedsum,elapsedsum2;
struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle;
char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
if ( didinit == 0 )
{
didinit = 1;
curl_global_init(CURL_GLOBAL_ALL); //init the curl session
}
numretries = 0;
if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 )
specialcase = 1;
else specialcase = 0;
if ( url[0] == 0 )
strcpy(url,"http://127.0.0.1:7876/nxt");
if ( specialcase != 0 && 0 )
printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params);
try_again:
if ( retstrp != 0 )
*retstrp = 0;
starttime = OS_milliseconds();
curl_handle = curl_easy_init();
init_string(&s);
headers = curl_slist_append(0,"Expect:");
curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
8 years ago
curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle,CURLOPT_URL, url);
8 years ago
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function
8 years ago
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
8 years ago
if ( strncmp(url,"https",5) == 0 )
{
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
}
if ( userpass != 0 )
curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass);
databuf = 0;
if ( params != 0 )
{
if ( command != 0 && specialcase == 0 )
{
len = strlen(params);
if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) {
bracket0 = bracket1 = (char *)"";
}
else
{
bracket0 = (char *)"[";
bracket1 = (char *)"]";
}
8 years ago
databuf = (char *)malloc(256 + strlen(command) + strlen(params));
sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
7 years ago
//printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
8 years ago
//
} //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
curl_easy_setopt(curl_handle,CURLOPT_POST,1L);
if ( databuf != 0 )
curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf);
else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params);
}
//laststart = milliseconds();
res = curl_easy_perform(curl_handle);
curl_slist_free_all(headers);
curl_easy_cleanup(curl_handle);
if ( databuf != 0 ) // clean up temporary buffer
{
free(databuf);
databuf = 0;
}
if ( res != CURLE_OK )
{
numretries++;
if ( specialcase != 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
free(s.ptr);
return(0);
}
8 years ago
else if ( numretries >= 1 )
8 years ago
{
8 years ago
//printf("Maximum number of retries exceeded!\n");
8 years ago
free(s.ptr);
return(0);
}
8 years ago
if ( (rand() % 1000) == 0 )
printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
8 years ago
free(s.ptr);
sleep((1<<numretries));
goto try_again;
8 years ago
}
else
{
if ( command != 0 && specialcase == 0 )
{
count++;
elapsedsum += (OS_milliseconds() - starttime);
8 years ago
if ( (count % 1000000) == 0)
8 years ago
printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
if ( retstrp != 0 )
{
*retstrp = s.ptr;
return(s.ptr);
}
return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params));
}
else
{
if ( 0 && specialcase != 0 )
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr);
count2++;
elapsedsum2 += (OS_milliseconds() - starttime);
if ( (count2 % 10000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command);
return(s.ptr);
}
}
printf("bitcoind_RPC: impossible case\n");
free(s.ptr);
return(0);
}
8 years ago
static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data)
{
size_t realsize = (size * nmemb);
struct MemoryStruct *mem = (struct MemoryStruct *)data;
8 years ago
mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1));
8 years ago
if ( mem->memory != 0 )
{
if ( ptr != 0 )
memcpy(&(mem->memory[mem->size]),ptr,realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
//printf("got %d bytes\n",(int32_t)(size*nmemb));
return(realsize);
}
8 years ago
char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3)
8 years ago
{
struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0;
if ( (cHandle= *cHandlep) == NULL )
*cHandlep = cHandle = curl_easy_init();
8 years ago
else curl_easy_reset(cHandle);
//#ifdef DEBUG
//curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1);
8 years ago
//#endif
curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0);
//curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1);
curl_easy_setopt(cHandle,CURLOPT_URL,url);
curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10);
8 years ago
if ( userpass != 0 && userpass[0] != 0 )
curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass);
if ( postfields != 0 && postfields[0] != 0 )
8 years ago
{
curl_easy_setopt(cHandle,CURLOPT_POST,1);
curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields);
8 years ago
}
if ( hdr0 != NULL && hdr0[0] != 0 )
{
//printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:"");
headers = curl_slist_append(headers,hdr0);
if ( hdr1 != 0 && hdr1[0] != 0 )
headers = curl_slist_append(headers,hdr1);
if ( hdr2 != 0 && hdr2[0] != 0 )
headers = curl_slist_append(headers,hdr2);
if ( hdr3 != 0 && hdr3[0] != 0 )
headers = curl_slist_append(headers,hdr3);
} //headers = curl_slist_append(0,"Expect:");
if ( headers != 0 )
curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers);
//res = curl_easy_perform(cHandle);
memset(&chunk,0,sizeof(chunk));
curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback);
curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk);
curl_easy_perform(cHandle);
curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code);
if ( headers != 0 )
curl_slist_free_all(headers);
if ( code != 200 )
printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory);
return(chunk.memory);
}
8 years ago
char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port)
8 years ago
{
6 years ago
//static void *cHandle;
8 years ago
char url[512],*retstr=0,*retstr2=0,postdata[8192];
8 years ago
if ( params == 0 || params[0] == 0 )
params = (char *)"[]";
8 years ago
if ( strlen(params) < sizeof(postdata)-128 )
{
8 years ago
sprintf(url,(char *)"http://127.0.0.1:%u",port);
8 years ago
sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
6 years ago
//printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS);
retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params);
//retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0);
8 years ago
}
8 years ago
return(retstr2);
8 years ago
}
7 years ago
int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp)
7 years ago
{
7 years ago
char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0;
7 years ago
params[0] = 0;
*kmdnotarized_heightp = 0;
7 years ago
if ( strcmp(dest,"KMD") == 0 )
7 years ago
{
7 years ago
port = KMD_PORT;
7 years ago
userpass = KMDUSERPASS;
}
else if ( strcmp(dest,"BTC") == 0 )
{
port = 8332;
userpass = BTCUSERPASS;
}
else return(0);
if ( userpass[0] != 0 )
{
if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 )
7 years ago
{
7 years ago
//printf("(%s)\n",jsonstr);
7 years ago
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
7 years ago
if ( (item= jobj(json,(char *)"result")) != 0 )
7 years ago
{
height = jint(item,(char *)"blocks");
7 years ago
*kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height;
7 years ago
}
7 years ago
free_json(json);
}
free(jsonstr);
}
sprintf(params,"[\"%s\", 1]",txidstr);
7 years ago
if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 )
7 years ago
{
7 years ago
//printf("(%s)\n",jsonstr);
7 years ago
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
7 years ago
if ( (item= jobj(json,(char *)"result")) != 0 )
7 years ago
{
txid_confirmations = jint(item,(char *)"confirmations");
if ( txid_confirmations > 0 && height > txid_confirmations )
txid_height = height - txid_confirmations;
7 years ago
else txid_height = height;
7 years ago
//printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height);
7 years ago
}
7 years ago
free_json(json);
}
free(jsonstr);
}
7 years ago
}
7 years ago
return(txid_height);
}
7 years ago
int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH)
7 years ago
{
int32_t i; uint256 hash; char params[256];
for (i=0; i<32; i++)
7 years ago
((uint8_t *)&hash)[i] = script[2+i];
7 years ago
if ( hash == NOTARIZED_HASH )
6 years ago
return(1);
7 years ago
for (i=0; i<32; i++)
printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]);
printf(" notarized, ");
for (i=0; i<32; i++)
printf("%02x",((uint8_t *)&hash)[i]);
6 years ago
printf(" opreturn from [%s] ht.%d MISMATCHED\n",ASSETCHAINS_SYMBOL,height);
7 years ago
return(-1);
7 years ago
}
int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID)
{
6 years ago
char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey;
script = _script;
7 years ago
/*params[0] = '[';
params[1] = '"';
for (i=0; i<32; i++)
sprintf(&params[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]);
strcat(params,"\", 1]");*/
7 years ago
sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str());
7 years ago
if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 )
return(0);
7 years ago
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
7 years ago
printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT);
7 years ago
if ( strcmp(dest,"KMD") == 0 )
7 years ago
{
if ( KMDUSERPASS[0] != 0 )
7 years ago
{
if ( ASSETCHAINS_SYMBOL[0] != 0 )
7 years ago
{
7 years ago
jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT);
//printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr);
7 years ago
}
}//else jsonstr = _dex_getrawtransaction();
7 years ago
else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok
7 years ago
}
7 years ago
else if ( strcmp(dest,"BTC") == 0 )
7 years ago
{
if ( BTCUSERPASS[0] != 0 )
7 years ago
{
7 years ago
//printf("BTCUSERPASS.(%s)\n",BTCUSERPASS);
7 years ago
jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,8332);
7 years ago
}
7 years ago
//else jsonstr = _dex_getrawtransaction();
7 years ago
else return(0);
7 years ago
}
7 years ago
else
{
printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest);
return(-1);
}
7 years ago
if ( jsonstr != 0 )
{
7 years ago
if ( (json= cJSON_Parse(jsonstr)) != 0 )
7 years ago
{
7 years ago
if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 )
7 years ago
{
vout = jitem(vouts,n-1);
7 years ago
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
7 years ago
printf("vout.(%s)\n",jprint(vout,0));
7 years ago
if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 )
7 years ago
{
7 years ago
if ( (hexstr= jstr(skey,(char *)"hex")) != 0 )
7 years ago
{
6 years ago
//printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str());
7 years ago
len = strlen(hexstr) >> 1;
decode_hex(script,len,hexstr);
6 years ago
if ( script[1] == 0x4c )
{
script++;
len--;
}
else if ( script[1] == 0x4d )
{
script += 2;
len -= 2;
}
7 years ago
retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH);
7 years ago
}
}
}
free_json(txjson);
}
free(jsonstr);
}
return(retval);
}
7 years ago
/*uint256 komodo_getblockhash(int32_t height)
{
uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32];
memset(&hash,0,sizeof(hash));
sprintf(params,"[%d]",height);
if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_RPCPORT)) != 0 )
{
if ( (result= cJSON_Parse(jsonstr)) != 0 )
{
if ( (hexstr= jstr(result,(char *)"result")) != 0 )
{
if ( is_hexstr(hexstr,0) == 64 )
{
decode_hex(revbuf,32,hexstr);
for (i=0; i<32; i++)
((uint8_t *)&hash)[i] = revbuf[31-i];
}
}
free_json(result);
}
printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash);
free(jsonstr);
}
return(hash);
}
uint256 _komodo_getblockhash(int32_t height);*/
8 years ago
8 years ago
uint64_t komodo_seed(int32_t height)
{
8 years ago
uint64_t seed = 0;
7 years ago
/*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds...
{
uint256 hash,zero; CBlockIndex *pindex;
memset(&hash,0,sizeof(hash));
memset(&zero,0,sizeof(zero));
if ( height > 10 )
height -= 10;
if ( ASSETCHAINS_SYMBOL[0] == 0 )
hash = _komodo_getblockhash(height);
if ( memcmp(&hash,&zero,sizeof(hash)) == 0 )
hash = komodo_getblockhash(height);
int32_t i;
for (i=0; i<32; i++)
printf("%02x",((uint8_t *)&hash)[i]);
printf(" seed.%d\n",height);
seed = arith_uint256(hash.GetHex()).GetLow64();
}
else*/
8 years ago
{
8 years ago
seed = (height << 13) ^ (height << 2);
seed <<= 21;
8 years ago
seed |= (height & 0xffffffff);
8 years ago
seed ^= (seed << 17) ^ (seed << 1);
8 years ago
}
8 years ago
return(seed);
}
6 years ago
uint32_t komodo_txtime(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
8 years ago
{
6 years ago
CTxDestination address; CTransaction tx; uint256 hashBlock;
6 years ago
*valuep = 0;
8 years ago
if (!GetTransaction(hash, tx,
#ifndef KOMODO_ZCASH
Params().GetConsensus(),
#endif
hashBlock, true))
8 years ago
{
6 years ago
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
6 years ago
return(0);
8 years ago
}
6 years ago
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
6 years ago
if ( n < tx.vout.size() )
6 years ago
{
6 years ago
*valuep = tx.vout[n].nValue;
6 years ago
if (ExtractDestination(tx.vout[n].scriptPubKey, address))
strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
6 years ago
}
6 years ago
return(tx.nLockTime);
8 years ago
}
6 years ago
uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
{
CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0;
*valuep = 0;
if (!GetTransaction(hash, tx,
#ifndef KOMODO_ZCASH
Params().GetConsensus(),
#endif
hashBlock, true))
{
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
return(0);
}
6 years ago
if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
6 years ago
txtime = pindex->nTime;
else txtime = tx.nLockTime;
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
if ( n < tx.vout.size() )
{
*valuep = tx.vout[n].nValue;
if (ExtractDestination(tx.vout[n].scriptPubKey, address))
strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
}
return(txtime);
}
6 years ago
int32_t komodo_isPoS(CBlock *pblock)
{
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid;
if ( ASSETCHAINS_STAKED != 0 )
{
if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 )
{
txid = pblock->vtx[n-1].vin[0].prevout.hash;
vout = pblock->vtx[n-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) )
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[n-1].vout[0].nValue == value )
{
6 years ago
//fprintf(stderr,"is PoS block!\n");
6 years ago
return(1);
}
}
}
}
return(0);
}
8 years ago
void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
{
char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
7 years ago
//fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight);
8 years ago
komodo_init(pindex->nHeight);
8 years ago
if ( (sp= komodo_stateptr(symbol,dest)) != 0 )
8 years ago
{
8 years ago
//sp->rewinding = pindex->nHeight;
//fprintf(stderr,"-%d ",pindex->nHeight);
8 years ago
} else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL);
8 years ago
}
8 years ago
int32_t komodo_is_notarytx(const CTransaction& tx)
{
uint8_t *ptr; static uint8_t crypto777[33];
7 years ago
if ( tx.vout.size() > 0 )
{
8 years ago
#ifdef KOMODO_ZCASH
7 years ago
ptr = (uint8_t *)tx.vout[0].scriptPubKey.data();
8 years ago
#else
7 years ago
ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0];
8 years ago
#endif
7 years ago
if ( ptr != 0 )
7 years ago
{
if ( crypto777[0] == 0 )
decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR);
7 years ago
if ( memcmp(ptr+1,crypto777,33) == 0 )
{
//printf("found notarytx\n");
return(1);
}
7 years ago
}
8 years ago
}
7 years ago
return(0);
8 years ago
}
8 years ago
int32_t komodo_block2height(CBlock *block)
{
6 years ago
static uint32_t match,mismatch;
int32_t i,n,height2=-1,height = 0; uint8_t *ptr; CBlockIndex *pindex;
if ( (pindex= mapBlockIndex[block->GetHash()]) != 0 )
6 years ago
{
height2 = (int32_t)pindex->nHeight;
6 years ago
if ( height2 >= 0 )
return(height2);
}
7 years ago
if ( block->vtx[0].vin.size() > 0 )
{
8 years ago
#ifdef KOMODO_ZCASH
7 years ago
ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
8 years ago
#else
7 years ago
ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
8 years ago
#endif
7 years ago
if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 )
8 years ago
{
7 years ago
//for (i=0; i<6; i++)
// printf("%02x",ptr[i]);
n = ptr[0];
6 years ago
for (i=0; i<n; i++) // looks strange but this works
7 years ago
{
//03bb81000101(bb 187) (81 48001) (00 12288256) <- coinbase.6 ht.12288256
height += ((uint32_t)ptr[i+1] << (i*8));
//printf("(%02x %x %d) ",ptr[i+1],((uint32_t)ptr[i+1] << (i*8)),height);
}
6 years ago
//printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height);
8 years ago
}
7 years ago
//komodo_init(height);
8 years ago
}
6 years ago
if ( height != height2 )
{
6 years ago
//fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch);
6 years ago
mismatch++;
if ( height2 >= 0 )
6 years ago
height = height2;
6 years ago
} else match++;
8 years ago
return(height);
}
6 years ago
int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block)
8 years ago
{
8 years ago
int32_t n;
6 years ago
if ( KOMODO_LOADINGBLOCKS == 0 )
memset(pubkey33,0xff,33);
else memset(pubkey33,0,33);
6 years ago
if ( block->vtx[0].vout.size() > 0 )
7 years ago
{
8 years ago
#ifdef KOMODO_ZCASH
6 years ago
uint8_t *ptr = (uint8_t *)block->vtx[0].vout[0].scriptPubKey.data();
8 years ago
#else
6 years ago
uint8_t *ptr = (uint8_t *)&block->vtx[0].vout[0].scriptPubKey[0];
8 years ago
#endif
7 years ago
//komodo_init(0);
6 years ago
n = block->vtx[0].vout[0].scriptPubKey.size();
7 years ago
if ( n == 35 )
6 years ago
{
7 years ago
memcpy(pubkey33,ptr+1,33);
6 years ago
return(1);
}
7 years ago
}
6 years ago
return(0);
8 years ago
}
8 years ago
int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex)
8 years ago
{
block.SetNull();
// Open history file to read
CAutoFile filein(OpenBlockFile(pindex->GetBlockPos(),true),SER_DISK,CLIENT_VERSION);
if (filein.IsNull())
return(-1);
// Read block
try { filein >> block; }
catch (const std::exception& e)
{
fprintf(stderr,"readblockfromdisk err B\n");
return(-1);
}
return(0);
}
6 years ago
uint32_t komodo_chainactive_timestamp()
{
if ( chainActive.Tip() != 0 )
return((uint32_t)chainActive.Tip()->GetBlockTime());
6 years ago
else return(0);
6 years ago
}
7 years ago
CBlockIndex *komodo_chainactive(int32_t height)
{
7 years ago
if ( chainActive.Tip() != 0 )
7 years ago
{
7 years ago
if ( height <= chainActive.Tip()->nHeight )
return(chainActive[height]);
7 years ago
// else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.Tip()->nHeight);
7 years ago
}
7 years ago
//fprintf(stderr,"komodo_chainactive null chainActive.Tip() height %d\n",height);
7 years ago
return(0);
7 years ago
}
uint32_t komodo_heightstamp(int32_t height)
{
7 years ago
CBlockIndex *ptr;
7 years ago
if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 )
7 years ago
return(ptr->nTime);
6 years ago
//else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height);
7 years ago
return(0);
}
6 years ago
/*void komodo_pindex_init(CBlockIndex *pindex,int32_t height) gets data corrupted
6 years ago
{
6 years ago
int32_t i,num; uint8_t pubkeys[64][33]; CBlock block;
6 years ago
if ( pindex->didinit != 0 )
6 years ago
return;
6 years ago
//printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->nHeight,pindex->notaryid,height);
6 years ago
if ( pindex->didinit == 0 )
6 years ago
{
6 years ago
pindex->notaryid = -1;
6 years ago
if ( KOMODO_LOADINGBLOCKS == 0 )
6 years ago
memset(pindex->pubkey33,0xff,33);
6 years ago
else memset(pindex->pubkey33,0,33);
6 years ago
if ( komodo_blockload(block,pindex) == 0 )
6 years ago
{
6 years ago
komodo_block2pubkey33(pindex->pubkey33,&block);
6 years ago
//for (i=0; i<33; i++)
// fprintf(stderr,"%02x",pindex->pubkey33[i]);
//fprintf(stderr," set pubkey at height %d/%d\n",pindex->nHeight,height);
6 years ago
//if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 )
6 years ago
// pindex->didinit = (KOMODO_LOADINGBLOCKS == 0);
6 years ago
} // else fprintf(stderr,"error loading block at %d/%d",pindex->nHeight,height);
6 years ago
}
6 years ago
if ( pindex->didinit != 0 && pindex->nHeight >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->nHeight,(uint32_t)pindex->nTime)) > 0 )
6 years ago
{
for (i=0; i<num; i++)
6 years ago
{
6 years ago
if ( memcmp(pubkeys[i],pindex->pubkey33,33) == 0 )
6 years ago
{
6 years ago
pindex->notaryid = i;
break;
6 years ago
}
}
6 years ago
if ( 0 && i == num )
6 years ago
{
for (i=0; i<33; i++)
fprintf(stderr,"%02x",pindex->pubkey33[i]);
fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->nHeight,height);
}
6 years ago
}
6 years ago
}*/
6 years ago
8 years ago
void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
{
6 years ago
int32_t num,i; CBlock block;
8 years ago
memset(pubkey33,0,33);
6 years ago
if ( pindex != 0 )
8 years ago
{
6 years ago
if ( komodo_blockload(block,pindex) == 0 )
komodo_block2pubkey33(pubkey33,&block);
8 years ago
}
}
6 years ago
/*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33)
8 years ago
{
6 years ago
int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33];
6 years ago
if ( (pindex= chainActive[height]) != 0 )
8 years ago
{
6 years ago
if ( pindex->didinit != 0 )
6 years ago
{
6 years ago
if ( destpubkey33 != 0 )
memcpy(destpubkey33,pindex->pubkey33,33);
6 years ago
return(pindex->notaryid);
6 years ago
}
6 years ago
komodo_index2pubkey33(pubkey33,pindex,height);
if ( destpubkey33 != 0 )
memcpy(destpubkey33,pindex->pubkey33,33);
if ( pindex->didinit != 0 )
return(pindex->notaryid);
6 years ago
timestamp = pindex->GetBlockTime();
6 years ago
if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 )
{
for (i=0; i<num; i++)
if ( memcmp(pubkeys[i],pubkey33,33) == 0 )
return(i);
6 years ago
}
7 years ago
}
6 years ago
fprintf(stderr,"komodo_minerid height.%d null pindex\n",height);
6 years ago
return(komodo_electednotary(&numnotaries,pubkey33,height,timestamp));
6 years ago
}*/
8 years ago
6 years ago
int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height)
7 years ago
{
6 years ago
int32_t i,j,n,duplicate; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33];
7 years ago
memset(mids,-1,sizeof(*mids)*66);
6 years ago
n = komodo_notaries(notarypubs33,height,0);
7 years ago
for (i=duplicate=0; i<66; i++)
{
7 years ago
if ( (pindex= komodo_chainactive(height-i)) != 0 )
7 years ago
{
6 years ago
blocktimes[i] = pindex->nTime;
6 years ago
if ( komodo_blockload(block,pindex) == 0 )
{
komodo_block2pubkey33(pubkeys[i],&block);
for (j=0; j<n; j++)
{
6 years ago
if ( memcmp(notarypubs33[j],pubkeys[i],33) == 0 )
6 years ago
{
mids[i] = j;
(*nonzpkeysp)++;
break;
}
}
6 years ago
} else fprintf(stderr,"couldnt load block.%d\n",height);
7 years ago
if ( mids[0] >= 0 && i > 0 && mids[i] == mids[0] )
duplicate++;
7 years ago
}
7 years ago
}
7 years ago
if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) )
7 years ago
return(1);
else return(0);
}
6 years ago
int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width)
8 years ago
{
6 years ago
int32_t i,j,n,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33];
numnotaries = komodo_notaries(notarypubs33,height,0);
for (i=nonz=0; i<width; i++,n++)
{
if ( height-i <= 0 )
continue;
if ( (pindex= komodo_chainactive(height-width+i+1)) != 0 )
{
if ( komodo_blockload(block,pindex) == 0 )
{
komodo_block2pubkey33(pubkey33,&block);
for (j=0; j<numnotaries; j++)
{
if ( memcmp(notarypubs33[j],pubkey33,33) == 0 )
{
minerids[nonz++] = j;
break;
}
}
6 years ago
if ( j == numnotaries )
minerids[nonz++] = j;
6 years ago
} else fprintf(stderr,"couldnt load block.%d\n",height);
}
}
return(nonz);
8 years ago
}
6 years ago
int32_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)
8 years ago
{
6 years ago
int32_t i,j,notaryid=0,minerid,limit,nid; uint8_t destpubkey33[33];
6 years ago
komodo_chosennotary(&notaryid,height,pubkey33,blocktimes[0]);
6 years ago
if ( height >= 82000 )
6 years ago
{
6 years ago
if ( notaryid >= 0 )
6 years ago
{
for (i=1; i<66; i++)
{
6 years ago
if ( mids[i] == notaryid )
6 years ago
{
6 years ago
if ( height > 792000 )
6 years ago
{
for (j=0; j<66; j++)
fprintf(stderr,"%d ",mids[j]);
fprintf(stderr,"ht.%d repeat notaryid.%d in mids[%d]\n",height,notaryid,i);
6 years ago
return(-1);
6 years ago
} else break;
6 years ago
}
}
6 years ago
if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 )
6 years ago
{
6 years ago
if ( height > 807000 )
6 years ago
return(-2);
6 years ago
}
return(1);
6 years ago
} else return(0);
}
6 years ago
else
8 years ago
{
6 years ago
if ( height >= 34000 && notaryid >= 0 )
8 years ago
{
6 years ago
if ( height < 79693 )
limit = 64;
else if ( height < 82000 )
limit = 8;
else limit = 66;
for (i=1; i<limit; i++)
8 years ago
{
6 years ago
komodo_chosennotary(&nid,height-i,pubkey33,blocktimes[i]);
6 years ago
if ( nid == notaryid )
{
6 years ago
//for (j=0; j<66; j++)
// fprintf(stderr,"%d ",mids[j]);
//fprintf(stderr,"ht.%d repeat mids[%d] nid.%d notaryid.%d\n",height-i,i,nid,notaryid);
6 years ago
if ( height > 225000 )
return(-1);
}
8 years ago
}
6 years ago
//fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit);
return(1);
8 years ago
}
}
return(0);
}
int32_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)
6 years ago
{
6 years ago
int32_t depth,notarized_ht; uint256 MoM,kmdtxid;
depth = komodo_MoMdata(&notarized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip);
6 years ago
memset(MoMp,0,sizeof(*MoMp));
6 years ago
memset(kmdtxidp,0,sizeof(*kmdtxidp));
6 years ago
*notarized_heightp = 0;
if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht )
6 years ago
{
*MoMp = MoM;
*notarized_heightp = notarized_ht;
6 years ago
*kmdtxidp = kmdtxid;
6 years ago
}
return(depth);
}
int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash)
{
int32_t notarized_height,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; CBlockIndex *notary,*pindex;
8 years ago
if ( (pindex= chainActive.Tip()) == 0 )
return(-1);
notarized_height = komodo_notarizeddata(pindex->nHeight,&notarized_hash,&notarized_desttxid);
*notarized_heightp = notarized_height;
8 years ago
if ( notarized_height >= 0 && notarized_height <= pindex->nHeight && (notary= mapBlockIndex[notarized_hash]) != 0 )
{
8 years ago
//printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->nHeight,notarized_height,notarized_hash.ToString().c_str());
if ( notary->nHeight == notarized_height ) // if notarized_hash not in chain, reorg
{
if ( nHeight < notarized_height )
{
6 years ago
//fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
return(-1);
}
else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
{
6 years ago
fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height);
return(-1);
}
6 years ago
} //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);
6 years ago
}
6 years ago
//else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 )
// fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->nHeight);
return(0);
}
8 years ago
7 years ago
uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n)
8 years ago
{
LOCK(cs_main);
CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex;
7 years ago
*txheighttimep = *txheightp = *tiptimep = 0;
*valuep = 0;
8 years ago
if ( !GetTransaction(hash,tx,hashBlock,true) )
return(0);
uint32_t locktime = 0;
if ( n < tx.vout.size() )
{
if ( (pindex= mapBlockIndex[hashBlock]) != 0 )
8 years ago
{
*valuep = tx.vout[n].nValue;
*txheightp = pindex->nHeight;
7 years ago
*txheighttimep = pindex->nTime;
if ( *tiptimep == 0 && (tipindex= chainActive.Tip()) != 0 )
*tiptimep = (uint32_t)tipindex->nTime;
8 years ago
locktime = tx.nLockTime;
8 years ago
//fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep);
8 years ago
}
}
return(locktime);
}
uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight)
8 years ago
{
uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex;
if ( (pindex= chainActive[tipheight]) != 0 )
tiptime = (uint32_t)pindex->nTime;
6 years ago
else fprintf(stderr,"cant find height[%d]\n",tipheight);
7 years ago
if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 )
8 years ago
{
8 years ago
if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) )
return(komodo_interest(*txheightp,value,*locktimep,tiptime));
8 years ago
//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);
8 years ago
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);
}
8 years ago
return(0);
}
8 years ago
int32_t komodo_isrealtime(int32_t *kmdheightp)
{
8 years ago
struct komodo_state *sp; CBlockIndex *pindex;
8 years ago
if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 )
8 years ago
*kmdheightp = sp->CURRENT_HEIGHT;
else *kmdheightp = 0;
7 years ago
if ( (pindex= chainActive.Tip()) != 0 && pindex->nHeight >= (int32_t)komodo_longestchain() )
8 years ago
return(1);
else return(0);
}
7 years ago
int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag)
7 years ago
{
6 years ago
if ( KOMODO_REWIND == 0 && (ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED != 0) && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
7 years ago
{
6 years ago
if ( txheight > 246748 || ASSETCHAINS_STAKED != 0 )
7 years ago
{
6 years ago
if ( txheight < 247205 && ASSETCHAINS_STAKED == 0 )
cmptime -= 16000;
if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME )
7 years ago
{
if ( tx.nLockTime != 1477258935 && dispflag != 0 )
7 years ago
{
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);
7 years ago
}
return(-1);
}
7 years ago
if ( 0 && dispflag != 0 )
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);
7 years ago
}
}
return(0);
}
6 years ago
/*
6 years ago
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.
komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass
commission must be in coinbase.vout[1] and must be >= 10000 sats
PoS stake must be without txfee and in the last tx in the block at vout[0]
*/
//#define KOMODO_POWMINMULT 16
uint64_t komodo_commission(const CBlock *pblock)
{
int32_t i,j,n=0,txn_count; uint64_t commission,total = 0;
txn_count = pblock->vtx.size();
for (i=0; i<txn_count; i++)
{
6 years ago
n = pblock->vtx[i].vout.size();
for (j=0; j<n; j++)
{
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(block.vtx[i].vout[j].nValue),j);
if ( i != 0 || j != 1 )
total += pblock->vtx[i].vout[j].nValue;
}
}
//fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN));
commission = ((total * ASSETCHAINS_COMMISSION) / COIN);
if ( commission < 10000 )
commission = 0;
return(commission);
}
uint32_t komodo_segid32(char *coinaddr)
{
bits256 addrhash;
6 years ago
vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr));
return(addrhash.uints[0]);
}
6 years ago
int8_t komodo_segid(int32_t height)
{
6 years ago
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;
6 years ago
if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 )
{
if ( komodo_blockload(block,pindex) == 0 )
{
6 years ago
txn_count = block.vtx.size();
if ( txn_count > 1 && block.vtx[txn_count-1].vin.size() == 1 && block.vtx[txn_count-1].vout.size() == 1 )
6 years ago
{
6 years ago
txid = block.vtx[txn_count-1].vin[0].prevout.hash;
vout = block.vtx[txn_count-1].vin[0].prevout.n;
6 years ago
txtime = komodo_txtime(&value,txid,vout,destaddr);
6 years ago
if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
6 years ago
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
6 years ago
if ( strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value )
6 years ago
{
segid = komodo_segid32(voutaddr) & 0x3f;
}
} else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height);
}
}
}
return(segid);
}
int32_t komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n)
{
static uint8_t prevhashbuf[100]; static int32_t prevheight;
int32_t i;
if ( height == prevheight && n == 100 )
memcpy(hashbuf,prevhashbuf,100);
else
{
memset(hashbuf,0xff,n);
for (i=0; i<n; i++)
{
hashbuf[i] = (uint8_t)komodo_segid(height+i);
6 years ago
//fprintf(stderr,"%02x ",hashbuf[i]);
6 years ago
}
if ( n == 100 )
{
memcpy(prevhashbuf,hashbuf,100);
prevheight = height;
6 years ago
//fprintf(stderr,"prevsegids.%d\n",height+n);
6 years ago
}
}
}
uint32_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)
6 years ago
{
6 years ago
bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio; uint256 hash,pasthash; int32_t diff=0,segid,minage,i,iter=0; uint32_t txtime,winner = 0 ; uint64_t value,coinage;
6 years ago
txtime = komodo_txtime2(&value,txid,vout,address);
6 years ago
if ( validateflag == 0 && blocktime < GetAdjustedTime() )
6 years ago
blocktime = GetAdjustedTime();
if ( blocktime < prevtime+3 )
blocktime = prevtime+3;
6 years ago
if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
{
6 years ago
//fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
6 years ago
return(0);
}
if ( value < SATOSHIDEN )
return(0);
6 years ago
value /= SATOSHIDEN;
6 years ago
mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
ratio = (mindiff / bnTarget);
6 years ago
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
segid = ((nHeight + addrhash.uints[0]) & 0x3f);
komodo_segids(hashbuf,nHeight-101,100);
memcpy(&hashbuf[100],&addrhash,sizeof(addrhash));
memcpy(&hashbuf[100+sizeof(addrhash)],&txid,sizeof(txid));
memcpy(&hashbuf[100+sizeof(addrhash)+sizeof(txid)],&vout,sizeof(vout));
vcalc_sha256(0,(uint8_t *)&hash,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout));
for (iter=0; iter<3600; iter++)
{
diff = (iter + blocktime - txtime - minage);
6 years ago
if ( diff < 0 )
diff = 60;
else if ( diff > 3600*24*30 )
6 years ago
{
6 years ago
//printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage);
6 years ago
diff = 3600*24*30;
6 years ago
}
6 years ago
if ( iter > 0 )
diff += segid*2;
if ( blocktime+iter+segid*2 < txtime+minage )
continue;
6 years ago
coinage = (value * diff);
6 years ago
hashval = ratio * (UintToArith256(hash) / arith_uint256(coinage+1));
6 years ago
if ( hashval <= bnTarget )
{
winner = 1;
if ( validateflag == 0 )
{
blocktime += iter;
blocktime += segid * 2;
}
break;
}
if ( validateflag != 0 )
{
6 years ago
/*for (i=31; i>=24; i--)
6 years ago
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
6 years ago
fprintf(stderr," vs ");
6 years ago
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
6 years ago
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);*/
6 years ago
break;
}
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
6 years ago
if ( 0 && validateflag != 0 )
6 years ago
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
6 years ago
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);
6 years ago
}
if ( nHeight < 10 )
return(blocktime);
return(blocktime * winner);
}
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc)
{
6 years ago
CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val;
*percPoSp = percPoS = 0;
if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) )
6 years ago
return(target);
sum = arith_uint256(0);
ave = sum;
easydiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
6 years ago
for (i=n=m=0; i<100; i++)
{
ht = height - 100 + i;
6 years ago
if ( ht <= 1 )
continue;
if ( (pindex= komodo_chainactive(ht)) != 0 )
6 years ago
{
if ( komodo_segid(ht) >= 0 )
{
n++;
percPoS++;
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"0");
}
else
{
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"1");
6 years ago
sum += UintToArith256(pindex->GetBlockHash());
6 years ago
m++;
}
}
/*if ( (pindex= komodo_chainactive(ht)) != 0 )
{
bnTarget.SetCompact(pindex->nBits,&fNegative,&fOverflow);
bnTarget = (bnTarget / arith_uint256(KOMODO_POWMINMULT));
hashval = UintToArith256(pindex->GetBlockHash());
6 years ago
if ( hashval <= bnTarget ) // PoW is never as easy as PoS/16, some PoS will be counted as PoW
{
6 years ago
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"1");
sum += hashval;
n++;
6 years ago
}
else
{
n++;
6 years ago
percPoS++;
6 years ago
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"0");
6 years ago
}
6 years ago
}*/
if ( ASSETCHAINS_STAKED < 100 && (i % 10) == 9 )
fprintf(stderr," %d, ",percPoS);
}
if ( m+n < 100 )
6 years ago
percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
6 years ago
if ( ASSETCHAINS_STAKED < 100 )
fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height);
*percPoSp = percPoS;
//target = (target / arith_uint256(KOMODO_POWMINMULT));
6 years ago
if ( m > 0 )
{
6 years ago
ave = (sum / arith_uint256(m));
if ( ave > target )
ave = target;
} else ave = easydiff; //else return(target);
if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
{
bnTarget = (ave * arith_uint256(percPoS * percPoS)) / arith_uint256(goalperc * goalperc * goalperc);
6 years ago
if ( ASSETCHAINS_STAKED < 100 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
fprintf(stderr," increase diff -> ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," floor diff ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
}
}
else if ( percPoS > goalperc ) // decrease PoW diff -> raise bnTarget
{
bnTarget = (ave * arith_uint256(percPoS * percPoS * percPoS)) / arith_uint256(goalperc * goalperc);
6 years ago
if ( bnTarget > easydiff )
bnTarget = easydiff;
6 years ago
else if ( bnTarget < ave ) // overflow
{
6 years ago
bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
if ( bnTarget < ave )
bnTarget = ave;
}
6 years ago
if ( 1 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&ave)[i]);
fprintf(stderr," decrease diff -> ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," floor diff ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&target)[i]);
fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
}
}
else bnTarget = ave; // recent ave is perfect
return(bnTarget);
}
6 years ago
int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget)
{
CBlockIndex *previndex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,txn_count,eligible=0,isPoS = 0; uint64_t value; CTxDestination voutaddress;
6 years ago
if ( ASSETCHAINS_STAKED == 100 && height <= 10 )
6 years ago
return(1);
txn_count = pblock->vtx.size();
if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 )
{
if ( prevtime == 0 )
{
if ( (previndex= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
prevtime = (uint32_t)previndex->nTime;
}
txid = pblock->vtx[txn_count-1].vin[0].prevout.hash;
vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
if ( prevtime != 0 )
{
6 years ago
if ( komodo_isPoS(pblock) != 0 )
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime,(char *)"");
if ( eligible == 0 || eligible > pblock->nTime )
{
6 years ago
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));
} else isPoS = 1;
}
if ( slowflag == 0 ) // maybe previous block is not seen yet, do the best approx
{
6 years ago
if ( komodo_isPoS(pblock) != 0 )
isPoS = 1;
/*txtime = komodo_txtime(&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
{
6 years ago
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
6 years ago
if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[txn_count-1].vout[0].nValue == value )
isPoS = 1; // close enough for a pre-filter
6 years ago
//else fprintf(stderr,"komodo_is_PoSblock ht.%d (%s) != (%s) or %.8f != %.8f\n",height,destaddr,voutaddr,dstr(value),dstr(pblock->vtx[txn_count-1].vout[0].nValue));
} else fprintf(stderr,"komodo_is_PoSblock ht.%d couldnt extract voutaddress\n",height);*/
} //else return(-1);
}
//fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS);
return(isPoS);
}
6 years ago
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
{
int64_t checktoshis=0; uint8_t *script;
if ( ASSETCHAINS_COMMISSION != 0 )
{
checktoshis = komodo_commission(pblock);
if ( checktoshis > 10000 && pblock->vtx[0].vout.size() != 2 )
return(-1);
else if ( checktoshis != 0 )
{
script = (uint8_t *)pblock->vtx[0].vout[1].scriptPubKey.data();
if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
return(-1);
if ( pblock->vtx[0].vout[1].nValue != checktoshis )
{
fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue));
return(-1);
}
}
}
return(checktoshis);
}
bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0;
int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
{
6 years ago
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;
if ( !CheckEquihashSolution(pblock, Params()) )
{
fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height);
return(-1);
}
6 years ago
hash = pblock->GetHash();
6 years ago
bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow);
6 years ago
bhash = UintToArith256(hash);
possible = komodo_block2pubkey33(pubkey33,pblock);
6 years ago
//fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget);
6 years ago
if ( height == 0 )
6 years ago
{
6 years ago
if ( slowflag != 0 )
return(0);
if ( (pprev= mapBlockIndex[pblock->hashPrevBlock]) != 0 )
height = pprev->nHeight + 1;
if ( height == 0 )
return(0);
6 years ago
}
6 years ago
if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget )
{
failed = 1;
6 years ago
if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case
{
if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 )
{
for (i=0; i<n; i++)
if ( memcmp(pubkey33,pubkeys[i],33) == 0 )
{
notaryid = i;
break;
}
}
}
6 years ago
else if ( possible == 0 || ASSETCHAINS_SYMBOL[0] != 0 )
{
6 years ago
if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW )
return(0);
if ( ASSETCHAINS_STAKED == 0 ) // komodo_is_PoSblock will check bnTarget
return(-1);
6 years ago
}
}
if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW
{
6 years ago
if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget)) == 0 )
{
6 years ago
if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64
return(-1);
else
{
if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target
return(0);
if ( slowflag != 0 )
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
if ( bhash > bnTarget )
{
for (i=31; i>=16; i--)
6 years ago
fprintf(stderr,"%02x",((uint8_t *)&bhash)[i]);
fprintf(stderr," > ");
for (i=31; i>=16; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED);
return(-1);
}
}
6 years ago
} else if ( is_PoSblock < 0 )
return(-1);
}
if ( failed == 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{
if ( height == 1 )
{
script = (uint8_t *)pblock->vtx[0].vout[0].scriptPubKey.data();
if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
return(-1);
}
else
{
if ( komodo_checkcommission(pblock,height) < 0 )
return(-1);
}
}
6 years ago
//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
if ( failed != 0 && possible == 0 && notaryid < 0 )
return(-1);
else return(0);
}