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.

2422 lines
97 KiB

// Copyright 2016-2020 The Hush Developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
8 years ago
/******************************************************************************
* Copyright © 2014-2019 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. *
* *
******************************************************************************/
// Hush functions that interact with bitcoind C++
7 years ago
#include <curl/curl.h>
#include <curl/easy.h>
#include "consensus/params.h"
#include "hush_defs.h"
#include "script/standard.h"
5 years ago
#include "cc/CCinclude.h"
#include "sietch.h"
7 years ago
int32_t hush_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
6 years ago
int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp);
int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp);
bool EnsureWalletIsAvailable(bool avoidException);
extern bool fRequestShutdown;
extern CScript KOMODO_EARLYTXID_SCRIPTPUB;
uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht);
uint32_t komodo_heightstamp(int32_t height);
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");
StartShutdown();
8 years ago
}
s->ptr[0] = '\0';
}
8 years ago
int tx_height( const uint256 &hash ){
int nHeight = 0;
CTransaction tx;
uint256 hashBlock;
if (!GetTransaction(hash, tx, hashBlock, true)) {
fprintf(stderr,"tx hash %s does not exist!\n", hash.ToString().c_str() );
return nHeight;
}
BlockMap::const_iterator it = mapBlockIndex.find(hashBlock);
if (it != mapBlockIndex.end()) {
nHeight = it->second->GetHeight();
//fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight);
} else {
// Unconfirmed xtns
fprintf(stderr,"tx %s is unconfirmed\n", hash.ToString().c_str() );
//fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() );
}
return nHeight;
}
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");
StartShutdown();
8 years ago
}
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:");
6 years ago
5 years ago
curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
5 years ago
curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
8 years ago
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
5 years ago
//curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
5 years ago
//curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2);
5 years ago
8 years ago
if ( strncmp(url,"https",5) == 0 )
{
/* printf("[ Decker ] SSL: %s\n", curl_version()); */
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
//curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); // this is useful for debug, but seems crash on libcurl/7.64.1 OpenSSL/1.1.1b zlib/1.2.8 librtmp/2.3
8 years ago
}
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 *)"]";
}
6 years ago
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 )
{
5 years ago
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
8 years ago
free(s.ptr);
return(0);
}
8 years ago
else if ( numretries >= 1 )
8 years ago
{
fprintf(stderr,"%s: Maximum number of retries exceeded!\n", __FUNCTION__);
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;
6 years ago
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);
//printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",SMART_CHAIN_SYMBOL,url,postdata,params,KMDUSERPASS);
6 years ago
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
{
6 years ago
txid_confirmations = jint(item,(char *)"rawconfirmations");
7 years ago
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]);
printf(" opreturn from [%s] ht.%d MISMATCHED\n",SMART_CHAIN_SYMBOL,height);
7 years ago
return(-1);
7 years ago
}
void komodo_reconsiderblock(uint256 blockhash)
{
char params[256],*jsonstr,*hexstr;
sprintf(params,"[\"%s\"]",blockhash.ToString().c_str());
if ( (jsonstr= komodo_issuemethod(ASSETCHAINS_USERPASS,(char *)"reconsiderblock",params,ASSETCHAINS_RPCPORT)) != 0 )
{
5 years ago
//fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> (%s)\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT,jsonstr);
free(jsonstr);
}
5 years ago
//fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> NULL\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT);
}
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());
if ( strcmp(symbol,SMART_CHAIN_SYMBOL[0]==0?(char *)"KMD":SMART_CHAIN_SYMBOL) != 0 )
7 years ago
return(0);
if ( 0 && SMART_CHAIN_SYMBOL[0] != 0 )
printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",SMART_CHAIN_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 ( SMART_CHAIN_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",SMART_CHAIN_SYMBOL,dest);
7 years ago
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);
if ( 0 && SMART_CHAIN_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);
}
CScript komodo_makeopret(CBlock *pblock, bool fNew)
{
std::vector<uint256> vLeaves;
vLeaves.push_back(pblock->hashPrevBlock);
for (int32_t i = 0; i < pblock->vtx.size()-(fNew ? 0 : 1); i++)
vLeaves.push_back(pblock->vtx[i].GetHash());
uint256 merkleroot = GetMerkleRoot(vLeaves);
CScript opret;
opret << OP_RETURN << E_MARSHAL(ss << merkleroot);
return(opret);
}
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);
}
6 years ago
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 ( SMART_CHAIN_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);
}
uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr)
8 years ago
{
CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts;
6 years ago
*valuep = 0;
8 years ago
if (!GetTransaction(hash, tx,
#ifndef HUSH_ZCASH
8 years ago
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
}
numvouts = tx.vout.size();
6 years ago
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
if ( n < numvouts )
6 years ago
{
6 years ago
*valuep = tx.vout[n].nValue;
opret = tx.vout[numvouts-1].scriptPubKey;
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
}
CBlockIndex *komodo_getblockindex(uint256 hash)
{
BlockMap::const_iterator it = mapBlockIndex.find(hash);
return((it != mapBlockIndex.end()) ? it->second : NULL);
}
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 HUSH_ZCASH
6 years ago
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);
}
if ( (pindex= komodo_getblockindex(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);
}
int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout)
{
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret;
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(opret,&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 )
{
//fprintf(stderr,"is PoS block!\n");
addressout = voutaddress;
return(1);
}
}
}
return(0);
}
5 years ago
bool komodo_checkopret(CBlock *pblock, CScript &merkleroot)
{
merkleroot = pblock->vtx.back().vout.back().scriptPubKey;
return(merkleroot.IsOpReturn() && merkleroot == komodo_makeopret(pblock, false));
}
extern const uint32_t nHushHardforkHeight;
bool hush_hardfork_active(uint32_t time)
5 years ago
{
//This allows simulating a different height via CLI option, with hardcoded height as default
uint32_t nHardForkHeight = GetArg("-hardfork-height", nHushHardforkHeight);
bool isactive = chainActive.Height() > nHardForkHeight;
if(fDebug) {
4 years ago
//fprintf(stderr, "%s: active=%d at height=%d and forkheight=%d\n", __FUNCTION__, (int)isactive, chainActive.Height(), nHardForkHeight);
}
return isactive;
5 years ago
}
int32_t komodo_isPoS(CBlock *pblock,int32_t height,bool fJustCheck)
{
6 years ago
return(0);
}
8 years ago
void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
{
char symbol[HUSH_SMART_CHAIN_MAXLEN],dest[HUSH_SMART_CHAIN_MAXLEN]; struct hush_state *sp;
//fprintf(stderr,"disconnect ht.%d\n",pindex->GetHeight());
komodo_init(pindex->GetHeight());
if ( (sp= hush_stateptr(symbol,dest)) != 0 )
8 years ago
{
//sp->rewinding = pindex->GetHeight();
//fprintf(stderr,"-%d ",pindex->GetHeight());
} else printf("komodo_disconnect: ht.%d cant get hush_state.(%s)\n",pindex->GetHeight(),SMART_CHAIN_SYMBOL);
8 years ago
}
8 years ago
int32_t komodo_is_notarytx(const CTransaction& tx)
{
uint8_t *ptr; static uint8_t crypto555[33];
7 years ago
if ( tx.vout.size() > 0 )
{
ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0];
if ( ptr != 0 )
7 years ago
{
if ( crypto555[0] == 0 )
decode_hex(crypto555,33,(char *)CRYPTO555_PUBSECPSTR);
if ( memcmp(ptr+1,crypto555,33) == 0 )
7 years ago
{
//printf("found notarytx\n");
return(1);
}
7 years ago
}
8 years ago
}
7 years ago
return(0);
8 years ago
}
int32_t hush_block2height(CBlock *block)
8 years ago
{
6 years ago
static uint32_t match,mismatch;
int32_t i,n,height2=-1,height = 0; uint8_t *ptr; CBlockIndex *pindex = NULL;
BlockMap::const_iterator it = mapBlockIndex.find(block->GetHash());
if ( it != mapBlockIndex.end() && (pindex = it->second) != 0 )
6 years ago
{
height2 = (int32_t)pindex->GetHeight();
6 years ago
if ( height2 >= 0 )
return(height2);
}
if ( pindex && block != 0 && block->vtx[0].vin.size() > 0 )
7 years ago
{
ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
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;
if ( HUSH_LOADINGBLOCKS == 0 )
6 years ago
memset(pubkey33,0xff,33);
else memset(pubkey33,0,33);
6 years ago
if ( block->vtx[0].vout.size() > 0 )
7 years ago
{
txnouttype whichType;
vector<vector<unsigned char>> vch = vector<vector<unsigned char>>();
if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY)
6 years ago
{
CPubKey pubKey(vch[0]);
if (pubKey.IsValid())
{
memcpy(pubkey33,vch[0].data(),33);
return true;
}
else memset(pubkey33,0,33);
6 years ago
}
else memset(pubkey33,0,33);
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.LastTip() != 0 )
return((uint32_t)chainActive.LastTip()->GetBlockTime());
6 years ago
else return(0);
6 years ago
}
7 years ago
CBlockIndex *komodo_chainactive(int32_t height)
{
if ( chainActive.LastTip() != 0 )
7 years ago
{
if ( height <= chainActive.LastTip()->GetHeight() )
7 years ago
return(chainActive[height]);
// else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->GetHeight());
7 years ago
}
//fprintf(stderr,"komodo_chainactive null chainActive.LastTip() 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;
//printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->GetHeight(),pindex->notaryid,height);
6 years ago
if ( pindex->didinit == 0 )
6 years ago
{
6 years ago
pindex->notaryid = -1;
if ( HUSH_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->GetHeight(),height);
6 years ago
//if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 )
// pindex->didinit = (HUSH_LOADINGBLOCKS == 0);
} // else fprintf(stderr,"error loading block at %d/%d",pindex->GetHeight(),height);
6 years ago
}
if ( pindex->didinit != 0 && pindex->GetHeight() >= 0 && (num= hush_notaries(pubkeys,(int32_t)pindex->GetHeight(),(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->GetHeight(),height);
6 years ago
}
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();
if ( (num= hush_notaries(pubkeys,height,timestamp)) > 0 )
6 years ago
{
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
{
// after the season HF block ALL new notaries instantly become elegible.
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);
n = hush_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,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33];
numnotaries = hush_notaries(notarypubs33,height,0);
6 years ago
for (i=nonz=0; i<width; i++)
6 years ago
{
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);
}
5 years ago
CBlockIndex *komodo_blockindex(uint256 hash)
{
BlockMap::const_iterator it; CBlockIndex *pindex = 0;
if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() )
pindex = it->second;
return(pindex);
}
int32_t komodo_blockheight(uint256 hash)
{
BlockMap::const_iterator it; CBlockIndex *pindex = 0;
if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() )
{
if ( (pindex= it->second) != 0 )
return(pindex->GetHeight());
}
return(0);
}
uint32_t komodo_blocktime(uint256 hash)
{
BlockMap::const_iterator it; CBlockIndex *pindex = 0;
if ( (it = mapBlockIndex.find(hash)) != mapBlockIndex.end() )
{
if ( (pindex= it->second) != 0 )
return(pindex->nTime);
}
return(0);
}
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;
if ( (pindex= chainActive.LastTip()) == 0 )
8 years ago
return(-1);
notarized_height = komodo_notarizeddata(pindex->GetHeight(),&notarized_hash,&notarized_desttxid);
*notarized_heightp = notarized_height;
BlockMap::const_iterator it;
if ( notarized_height >= 0 && notarized_height <= pindex->GetHeight() && (it = mapBlockIndex.find(notarized_hash)) != mapBlockIndex.end() && (notary = it->second) != NULL )
{
//printf("nHeight.%d -> (%d %s)\n",pindex->Tip()->GetHeight(),notarized_height,notarized_hash.ToString().c_str());
if ( notary->GetHeight() == notarized_height ) // if notarized_hash not in chain, reorg
{
if ( nHeight < notarized_height )
{
//fprintf(stderr,"[%s] nHeight.%d < NOTARIZED_HEIGHT.%d\n",SMART_CHAIN_SYMBOL,nHeight,notarized_height);
return(-1);
}
else if ( nHeight == notarized_height && memcmp(&hash,&notarized_hash,sizeof(hash)) != 0 )
{
fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",SMART_CHAIN_SYMBOL,nHeight,notarized_height);
return(-1);
}
} //else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",SMART_CHAIN_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->GetHeight());
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",SMART_CHAIN_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->GetHeight());
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= komodo_getblockindex(hashBlock)) != 0 )
8 years ago
{
*valuep = tx.vout[n].nValue;
*txheightp = pindex->GetHeight();
7 years ago
*txheighttimep = pindex->nTime;
if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 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_nextheight()
{
5 years ago
CBlockIndex *pindex; int32_t ht;
if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 )
return(ht+1);
else return(hush_longestchain() + 1);
}
8 years ago
int32_t komodo_isrealtime(int32_t *kmdheightp)
{
struct hush_state *sp; CBlockIndex *pindex;
if ( (sp= hush_stateptrget((char *)"KMD")) != 0 )
8 years ago
*kmdheightp = sp->CURRENT_HEIGHT;
else *kmdheightp = 0;
if ( (pindex= chainActive.LastTip()) != 0 && pindex->GetHeight() >= (int32_t)hush_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
{
dispflag = 1;
if ( HUSH_REWIND == 0 && SMART_CHAIN_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 )
7 years ago
{
if ( txheight > 246748 )
7 years ago
{
if ( txheight < 247205 )
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.
6 years ago
komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass
6 years ago
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]
*/
6 years ago
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
// This function defines the Hush Founders Reward (AKA Dev Tax)
// 10% of all block rewards go towards Hush core team
// If you do not like this, you are encouraged to fork the chain
// or start your own Hush Smart Chain: https://git.hush.is/hush/hush-smart-chains
// HUSH supply curve cannot be exactly represented via KMD AC CLI args, so we do it ourselves.
// You specify the BR, and the FR % gets added so 10% of 12.5 is 1.25
// but to tell the AC params, I need to say "11% of 11.25" is 1.25
// 11% ie. 1/9th cannot be exactly represented and so the FR has tiny amounts of error unless done manually
4 years ago
// This must be kept in sync with hush_block_subsidy() in hush_utils.h!
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
// Changing these functions are consensus changes!
// Here Be Dragons! -- Duke Leto
uint64_t hush_commission(int height)
{
int32_t starting_commission = 125000000, HALVING1 = GetArg("-z2zheight",340000),
INTERVAL = GetArg("-ac_halving1",840000), TRANSITION = 129;
uint64_t commission = 0;
//TODO: Likely a bug hiding here or at the next halving :)
//if( height >= HALVING1) {
if( height > HALVING1) {
// Block time going from 150s to 75s (half) means the interval between halvings
// must be twice as often, i.e. 840000*2=1680000
4 years ago
// 840000 is ~4 years worth of 150s blocks
// With 150s blocks, we have 210,000 blocks per year
// With 75s blocks, we have 420,000 blocks per year
4 years ago
INTERVAL = GetArg("-ac_halving2",1680000); // ~4 years worth of 75s blocks
//fprintf(stderr,"%s: height=%d increasing interval to %d\n", __func__, height, INTERVAL);
}
// Block 128 had a miner subsidy but no FR!!! Discovered by Denio
if (height < TRANSITION) {
commission = 0;
} else {
// Just like BTC, BRs in the far future will be slightly less than
// they should be because exact values are not integers, causing
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
// slightly less coins to be actually mined and small deviations
// to the ideal FR/devtax
if (height < HALVING1) { // before 1st Halving @ Block 340000 (Nov 2020)
commission = starting_commission;
} else if (height < 2020000 ) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
commission = 31250000;
} else if (height < 3700000 ) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
commission = 15625000;
} else if (height < 5380000 ) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
commission = 7812500;
} else if (height < 7060000 ) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
commission = 3906250;
} else if (height < 8740000 ) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
commission = 1953125;
} else if (height < 10420000) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
commission = 976562; // 0.5 puposhi deviation, all further BRs have deviation from ideal
} else if (height < 12100000) {
commission = 488281;
} else if (height < 15460000) {
commission = 244140;
} else if (height < 17140000) {
commission = 122070;
} else if (height < 18820000) {
commission = 61035;
} else if (height < 23860000) {
commission = 30517;
} else if (height < 23860000) {
commission = 15258;
} else if (height < 25540000) {
commission = 7629;
} else if (height < 27220000) {
commission = 3814;
} else if (height < 27220000) {
commission = 1907;
} else if (height < 28900000) {
commission = 953;
} else if (height < 30580000) {
commission = 476;
} else if (height < 32260000) {
commission = 238;
} else if (height < 33940000) {
commission = 119;
} else if (height < 35620000) {
commission = 59;
} else if (height < 37300000) {
commission = 29;
} else if (height < 38980000) {
commission = 14;
} else if (height < 40660000) {
commission = 7;
} else if (height < 42340000) {
commission = 3;
} else if (height < 44020000) {
commission = 1;
} else if (height < 45700000) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
// FR goes to zero at Halving 26
commission = 0;
} else if (height < 47380000) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
// FR still zero at Halving 27
commission = 0;
} else if (height < 49060000) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
// FR still zero at Halving 28
commission = 0;
} else if (height < 50740000) {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
// FR still zero at Halving 29
commission = 0;
} else {
Implement entire Hush block subsidy schedule We now have our halving schedule implemented until the BR goes to zero. The data was calculated via two new scripts which are in ./contrib : $ ./contrib/hush_halvings 1,12500000000,340000 2,312500000,2020000 3,156250000,3700000 4,78125000,5380000 5,39062500,7060000 6,19531250,8740000 7,9765625,10420000 8,4882812,12100000 9,2441406,13780000 10,1220703,15460000 11,610351,17140000 12,305175,18820000 13,152587,20500000 14,76293,22180000 15,38146,23860000 16,19073,25540000 17,9536,27220000 18,4768,28900000 19,2384,30580000 20,1192,32260000 21,596,33940000 22,298,35620000 23,149,37300000 24,74,38980000 25,37,40660000 26,18,42340000 27,9,44020000 28,4,45700000 29,2,47380000 30,1,49060000 31,0,50740000 32,0,52420000 33,0,54100000 $ ./contrib/hush_block_subsidy_per_halving 0,1250000000,1125000000,125000000 1,625000000,562500000,62500000 2,312500000,281250000,31250000 3,156250000,140625000,15625000 4,78125000,70312500,7812500 5,39062500,35156250,3906250 6,19531250,17578125,1953125 7,9765625,8789062,976562 8,4882812,4394531,488281 9,2441406,2197265,244140 10,1220703,1098632,122070 11,610351,549316,61035 12,305175,274658,30517 13,152587,137329,15258 14,76293,68664,7629 15,38146,34332,3814 16,19073,17166,1907 17,9536,8583,953 18,4768,4291,476 19,2384,2145,238 20,1192,1072,119 21,596,536,59 22,298,268,29 23,149,134,14 24,74,67,7 25,37,33,3 26,18,16,1 27,9,8,0 28,4,4,0 29,2,2,0 30,1,1,0 31,0,0,0 These show that the block subsidy for miners goes to 0 at the 31st halving and that the Founders Reward AKA Dev Tax goes to 0 at the 27th halving. There is also some current KMD internals code that we inherited that prevents the FR from being less than 10000, so that code would currently set our FR to 0 at the 14th halving and lead less HUSH being mined than the planned 21M and even a bit less than the amount under 21M that normally happens, such as in BTC. We have some time to deal with the bug, since halving 14 is in about 52 years.
4 years ago
// enforce FR=0 for all other heights
// This over-rides the -ac_end param via HUSH3 cli args
commission = 0;
}
}
if(fDebug)
fprintf(stderr,"%s: commission=%lu,interval=%d at height %d\n", __func__, commission, INTERVAL, height);
return commission;
}
uint64_t the_commission(const CBlock *pblock,int32_t height)
{
//fprintf(stderr,"%s at height=%d\n",__func__,height);
4 years ago
static bool didinit = false, ishush3 = false;
if (!didinit) {
ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false;
didinit = true;
fprintf(stderr,"%s: didinit ishush3=%d\n", __func__, ishush3);
}
6 years ago
int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0;
6 years ago
if ( ASSETCHAINS_FOUNDERS != 0 )
{
6 years ago
nSubsidy = GetBlockSubsidy(height,Params().GetConsensus());
if(fDebug)
fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION));
6 years ago
commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN);
if (ishush3) {
commission = hush_commission(height);
}
if ( ASSETCHAINS_FOUNDERS > 1 )
{
if ( (height % ASSETCHAINS_FOUNDERS) == 0 )
{
if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) {
commission = commission * ASSETCHAINS_FOUNDERS;
} else {
commission = ASSETCHAINS_FOUNDERS_REWARD;
}
if(fDebug)
fprintf(stderr,"%s: set commission=%lu at height %d with\n",__func__,commission, height);
} else {
commission = 0;
}
}
} else if ( pblock != 0 ) {
txn_count = pblock->vtx.size();
6 years ago
for (i=0; i<txn_count; i++)
{
6 years ago
n = pblock->vtx[i].vout.size();
6 years ago
for (j=0; j<n; j++)
{
5 years ago
if ( height > 225000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 )
break;
5 years ago
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j);
6 years ago
if ( i != 0 || j != 1 )
total += pblock->vtx[i].vout[j].nValue;
if ( total > 1000000 * COIN )
5 years ago
{
total = 1000000 * COIN;
5 years ago
break;
}
6 years ago
}
}
commission = ((total / 10000) * ASSETCHAINS_COMMISSION) / 10000;
//commission = ((total * ASSETCHAINS_COMMISSION) / COIN);
6 years ago
}
if ( commission < 10000 )
commission = 0;
if(fDebug)
fprintf(stderr,"%s: commission=%.8f at height=%d\n",__func__, (double)commission/COIN, height);
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]);
}
int8_t komodo_segid(int32_t nocache,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; CScript opret; int8_t segid = -1;
6 years ago
if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 )
{
if ( nocache == 0 && pindex->segid >= -1 )
6 years ago
return(pindex->segid);
6 years ago
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;
txtime = komodo_txtime(opret,&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;
5 years ago
pindex->segid = segid;
//fprintf(stderr,"komodo_segid.(%d) -> %d\n",height,pindex->segid);
6 years ago
}
} else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height);
}
}
}
return(segid);
}
void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n)
6 years ago
{
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(1,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
}
}
}
6 years ago
uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout)
{
6 years ago
bits256 addrhash;
6 years ago
vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)address,(int32_t)strlen(address));
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 *)hashp,hashbuf,100 + (int32_t)sizeof(uint256)*2 + sizeof(vout));
return(addrhash.uints[0]);
}
arith_uint256 komodo_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime)
{
5 years ago
arith_uint256 origtarget,easy; int32_t diff,tipdiff; int64_t mult; bool fNegative,fOverflow; CBlockIndex *tipindex;
if ( height > 10 && (tipindex= komodo_chainactive(height - 1)) != 0 ) // disable offchain diffchange
{
diff = (nTime - tipindex->GetMedianTimePast());
5 years ago
tipdiff = (nTime - tipindex->nTime);
if ( tipdiff > 13*ASSETCHAINS_BLOCKTIME )
5 years ago
diff = tipdiff;
if ( diff >= 13 * ASSETCHAINS_BLOCKTIME && (height < 30 || tipdiff > 2*ASSETCHAINS_BLOCKTIME) )
{
5 years ago
mult = diff - 12 * ASSETCHAINS_BLOCKTIME;
mult = (mult / ASSETCHAINS_BLOCKTIME) * ASSETCHAINS_BLOCKTIME + ASSETCHAINS_BLOCKTIME / 2;
origtarget = bnTarget;
bnTarget = bnTarget * arith_uint256(mult * mult);
easy.SetCompact(HUSH_MINDIFF_NBITS,&fNegative,&fOverflow);
if ( bnTarget < origtarget || bnTarget > easy ) // deal with overflow
{
bnTarget = easy;
5 years ago
fprintf(stderr,"tipdiff.%d diff.%d height.%d miner overflowed mult.%lld, set to mindiff\n",tipdiff,diff,height,(long long)mult);
} else fprintf(stderr,"tipdiff.%d diff.%d height.%d miner elapsed %d, adjust by factor of %lld\n",tipdiff,diff,height,diff,(long long)mult);
5 years ago
} //else fprintf(stderr,"height.%d tipdiff.%d diff %d, vs %d\n",height,tipdiff,diff,13*ASSETCHAINS_BLOCKTIME);
} else fprintf(stderr,"adaptive cant find height.%d\n",height);
return(bnTarget);
}
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc)
{
int32_t oldflag = 0,dispflag = 0;
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(STAKING_MIN_DIFF,&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
{
6 years ago
if ( komodo_segid(0,ht) >= 0 )
6 years ago
{
n++;
percPoS++;
if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 )
6 years ago
fprintf(stderr,"0");
}
else
{
if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 )
6 years ago
fprintf(stderr,"1");
6 years ago
sum += UintToArith256(pindex->GetBlockHash());
6 years ago
m++;
}
} //else fprintf(stderr, "pindex returned null ht.%i\n",ht);
if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9 )
6 years ago
fprintf(stderr," %d, ",percPoS);
}
if ( m+n < 100 )
{
5 years ago
percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
}
if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 )
6 years ago
fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height);
*percPoSp = percPoS;
6 years ago
if ( m > 0 )
{
6 years ago
ave = (sum / arith_uint256(m));
if ( ave > target )
ave = target;
6 years ago
} else ave = target; //easydiff; //else return(target);
if ( percPoS == 0 )
percPoS = 1;
if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget
{
if ( oldflag != 0 )
6 years ago
bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS);
else bnTarget = (ave / arith_uint256(goalperc * goalperc * goalperc * goalperc)) * arith_uint256(percPoS * percPoS);
if ( dispflag != 0 && 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
{
if ( oldflag != 0 )
{
bnTarget = ((ave * arith_uint256(goalperc)) + (easydiff * arith_uint256(percPoS))) / arith_uint256(percPoS + goalperc);
bnTarget = (bnTarget / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS);
6 years ago
}
else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS);
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;
}
if ( dispflag != 0 )
{
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);
}
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,int32_t PoSperc)
{
5 years ago
bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio,coinage256; uint256 hash,pasthash; int32_t segid,minage,i,iter=0; int64_t diff=0; uint32_t txtime,segid32,winner = 0 ; uint64_t value,coinage;
txtime = komodo_txtime2(&value,txid,vout,address);
if ( validateflag == 0 )
{
//fprintf(stderr,"blocktime.%u -> ",blocktime);
if ( blocktime < prevtime+3 )
blocktime = prevtime+3;
if ( blocktime < GetTime()-60 )
blocktime = GetTime()+30;
//fprintf(stderr,"blocktime.%u txtime.%u\n",blocktime,txtime);
}
if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
{
//fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
return(0);
}
if ( value < SATOSHIDEN )
return(0);
value /= SATOSHIDEN;
mindiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow);
ratio = (mindiff / bnTarget);
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
komodo_segids(hashbuf,nHeight-101,100);
segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
segid = ((nHeight + segid32) & 0x3f);
for (iter=0; iter<600; iter++)
{
if ( blocktime+iter+segid*2 < txtime+minage )
continue;
diff = (iter + blocktime - txtime - minage);
if ( diff < 0 )
diff = 60;
else if ( diff > 3600*24*30 )
{
//printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage);
diff = 3600*24*30;
}
if ( iter > 0 )
diff += segid*2;
coinage = (value * diff);
if ( blocktime+iter+segid*2 > prevtime+480 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
coinage256 = arith_uint256(coinage+1);
hashval = ratio * (UintToArith256(hash) / coinage256);
if ( hashval <= bnTarget )
{
winner = 1;
if ( validateflag == 0 )
{
//fprintf(stderr,"winner blocktime.%u iter.%d segid.%d\n",blocktime,iter,segid);
blocktime += iter;
blocktime += segid * 2;
}
break;
}
if ( validateflag != 0 )
{
/*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]);
5 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); */
break;
}
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
if ( 0 && validateflag != 0 )
{
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]);
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);
}
if ( nHeight < 10 )
return(blocktime);
return(blocktime * winner);
}
int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget,arith_uint256 bhash)
{
CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t ret,vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress; arith_uint256 POWTarget;
if ( ASSETCHAINS_STAKED == 100 && height <= 10 )
6 years ago
return(1);
BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash());
pindex = it != mapBlockIndex.end() ? it->second : NULL;
6 years ago
if ( pindex != 0 && pindex->segid >= -1 )
6 years ago
{
5 years ago
//fprintf(stderr,"isPoSblock segid.%d\n",pindex->segid);
6 years ago
if ( pindex->segid == -1 )
return(0);
else return(1);
6 years ago
}
// Get PoSperc and POW Target. slowflag only here, calling it when blocks out of order causes problems.
if ( slowflag != 0 )
POWTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
txn_count = pblock->vtx.size();
5 years ago
//fprintf(stderr,"checkblock n.%d vins.%d vouts.%d %.8f %.8f\n",txn_count,(int32_t)pblock->vtx[txn_count-1].vin.size(),(int32_t)pblock->vtx[txn_count-1].vout.size(),(double)pblock->vtx[txn_count-1].vout[0].nValue/COIN,(double)pblock->vtx[txn_count-1].vout[1].nValue/COIN);
5 years ago
if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 + (ASSETCHAINS_MARMARA!=0) )
{
it = mapBlockIndex.find(pblock->hashPrevBlock);
if ( it != mapBlockIndex.end() && (previndex = it->second) != NULL )
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 ( slowflag != 0 && prevtime != 0 )
{
if ( komodo_isPoS(pblock,height,false) != 0 )
6 years ago
{
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"",PoSperc);
6 years ago
}
if ( eligible == 0 || eligible > pblock->nTime )
{
if ( 0 && ASSETCHAINS_STAKED < 100 )
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));
if ( pindex != 0 )
6 years ago
{
6 years ago
pindex->segid = -1;
//fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid);
6 years ago
}
6 years ago
}
else
{
isPoS = 2; // 2 means staking utxo validated
CTxDestination voutaddress; char voutaddr[64];
if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
6 years ago
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
segid = komodo_segid32(voutaddr) & 0x3f;
6 years ago
}
if ( pindex != 0 && segid >= 0 )
{
pindex->segid = segid;
//fprintf(stderr,"PoS block set segid.%d <- %d\n",height,pindex->segid);
} //else fprintf(stderr,"unexpected null pindex for slowflag set ht.%d segid.%d:%d\n",height,pindex!=0?pindex->segid:-3,segid);
6 years ago
}
}
else if ( slowflag == 0 ) // previous blocks are not seen yet, do the best approx
{
if ( komodo_isPoS(pblock,height,false) != 0 )
isPoS = 1;
}
if ( slowflag != 0 && isPoS != 0 )
{
6 years ago
if ( isPoS != 2 )
{
6 years ago
fprintf(stderr,"ht.%d isPoS.%d utxo not validated -> must be PoW fake\n",height,isPoS);
isPoS = 0;
}
else if ( ASSETCHAINS_STAKED != 100 )
6 years ago
{
if ( bhash < POWTarget )
6 years ago
{
6 years ago
//fprintf(stderr,"ht.%d isPoS but meets PoW diff!\n",height);
6 years ago
isPoS = 0;
}
}
}
//else return(-1);
}
//fprintf(stderr,"slow.%d ht.%d isPoS.%d\n",slowflag,height,isPoS);
return(isPoS != 0);
}
bool GetStakeParams(const CTransaction &stakeTx, CStakeParams &stakeParams);
bool ValidateMatchingStake(const CTransaction &ccTx, uint32_t voutNum, const CTransaction &stakeTx, bool &cheating);
uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount)
{
int8_t curEra = 0; int64_t ret = 0;
// if we have an end block in the first era, find our current era
if ( ASSETCHAINS_ENDSUBSIDY[0] > 1 )
{
for ( curEra = 0; curEra <= ASSETCHAINS_LASTERA; curEra++ )
{
if ( ASSETCHAINS_ENDSUBSIDY[curEra] > nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 )
break;
}
}
if ( curEra > ASSETCHAINS_LASTERA )
return(0);
if ( notarycount == 0 )
{
fprintf(stderr, "komodo_notarypayamount failed num notaries is 0!\n");
return(0);
}
// Because of reorgs we cannot use the notarized height value.
// We need to basically guess here and just pay some static amount.
// Has the unwanted effect of varying coin emission, but cannot be helped.
//fprintf(stderr, "era.%i paying total of %lu\n",curEra, ASSETCHAINS_NOTARY_PAY[curEra]);
ret = ASSETCHAINS_NOTARY_PAY[curEra] / notarycount;
return(ret);
}
int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len)
5 years ago
{
// Check the notarisation is valid, and extract notarised height.
uint64_t voutmask;
uint8_t scriptbuf[10001];
int32_t isratification,specialtx,notarizedheight;
if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) )
{
memcpy(scriptbuf,script,len);
if ( komodo_voutupdate(true,&isratification,0,scriptbuf,len,height,uint256(),1,1,&voutmask,&specialtx,&notarizedheight,0,1,0,timestamp) != -2 )
{
fprintf(stderr, "<<<<<<INVALID NOTARIZATION ht.%i\n",notarizedheight);
return(0);
}
} else return(0);
return(notarizedheight);
}
uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &NotarizationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len)
{
// fetch notary pubkey array.
uint64_t total = 0, AmountToPay = 0;
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
numSN = hush_notaries(notarypubkeys, height, timestamp);
// No point going further, no notaries can be paid.
if ( notarypubkeys[0][0] == 0 )
return(0);
// Check the notarisation is valid.
int32_t notarizedheight = komodo_getnotarizedheight(timestamp, height, script, len);
if ( notarizedheight == 0 )
return(0);
// resize coinbase vouts to number of notary nodes +1 for coinbase itself.
txNew.vout.resize(NotarizationNotaries.size()+1);
// Calcualte the amount to pay according to the current era.
AmountToPay = komodo_notarypayamount(height,NotarizationNotaries.size());
if ( AmountToPay == 0 )
return(0);
5 years ago
// loop over notarisation vins and add transaction to coinbase.
// Commented prints here can be used to verify manually the pubkeys match.
for (int8_t n = 0; n < NotarizationNotaries.size(); n++)
5 years ago
{
uint8_t *ptr;
txNew.vout[n+1].scriptPubKey.resize(35);
ptr = (uint8_t *)&txNew.vout[n+1].scriptPubKey[0];
ptr[0] = 33;
for (int8_t i=0; i<33; i++)
{
ptr[i+1] = notarypubkeys[NotarizationNotaries[n]][i];
5 years ago
//fprintf(stderr,"%02x",ptr[i+1]);
}
ptr[34] = OP_CHECKSIG;
//fprintf(stderr," set notary %i PUBKEY33 into vout[%i] amount.%lu\n",NotarizationNotaries[n],n+1,AmountToPay);
txNew.vout[n+1].nValue = AmountToPay;
5 years ago
total += txNew.vout[n+1].nValue;
}
return(total);
}
bool GetNotarizationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector<CTxIn> &vin, std::vector<int8_t> &NotarizationNotaries)
5 years ago
{
uint8_t *script; int32_t scriptlen;
5 years ago
if ( notarypubkeys[0][0] == 0 )
return false;
BOOST_FOREACH(const CTxIn& txin, vin)
5 years ago
{
uint256 hash; CTransaction tx1;
if ( GetTransaction(txin.prevout.hash,tx1,hash,false) )
{
5 years ago
for (int8_t i = 0; i < numNN; i++)
5 years ago
{
script = (uint8_t *)&tx1.vout[txin.prevout.n].scriptPubKey[0];
scriptlen = (int32_t)tx1.vout[txin.prevout.n].scriptPubKey.size();
if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[i],33) == 0 )
NotarizationNotaries.push_back(i);
5 years ago
}
5 years ago
} else return false;
5 years ago
}
5 years ago
return true;
}
uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height)
{
std::vector<int8_t> NotarizationNotaries; uint8_t *script; int32_t scriptlen;
5 years ago
uint64_t timestamp = pblock->nTime;
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
numSN = hush_notaries(notarypubkeys, height, timestamp);
if ( !GetNotarizationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarizationNotaries) )
5 years ago
return(0);
// check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems)
std::set<int> checkdupes( NotarizationNotaries.begin(), NotarizationNotaries.end() );
if ( checkdupes.size() != NotarizationNotaries.size() ) {
fprintf(stderr, "Possible notarisation is signed multiple times by same notary. It is invalid.\n");
return(0);
}
5 years ago
const CChainParams& chainparams = Params();
const Consensus::Params &consensusParams = chainparams.GetConsensus();
uint64_t totalsats = 0;
5 years ago
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, height);
if ( pblock->vtx[1].vout.size() == 2 && pblock->vtx[1].vout[1].nValue == 0 )
{
// Get the OP_RETURN for the notarisation
uint8_t *script = (uint8_t *)&pblock->vtx[1].vout[1].scriptPubKey[0];
int32_t scriptlen = (int32_t)pblock->vtx[1].vout[1].scriptPubKey.size();
if ( script[0] == OP_RETURN )
{
// Create the coinbase tx again, using the extracted data, this is the same function the miner uses, with the same data.
// This allows us to know exactly that the coinbase is correct.
totalsats = komodo_notarypay(txNew, NotarizationNotaries, pblock->nTime, height, script, scriptlen);
}
else
{
fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen);
return(0);
}
} else return(0);
// if notarypay fails, because the notarisation is not valid, exit now as txNew was not created.
// This should never happen, as the notarisation is checked before this function is called.
if ( totalsats == 0 )
{
fprintf(stderr, "notary pay returned 0!\n");
5 years ago
return(0);
}
5 years ago
int8_t n = 0, i = 0, matches = 0;
uint64_t total = 0, AmountToPay = 0;
// get the pay amount from the created tx.
AmountToPay = txNew.vout[1].nValue;
// Check the created coinbase pays the correct notaries.
BOOST_FOREACH(const CTxOut& txout, pblock->vtx[0].vout)
5 years ago
{
// skip the coinbase paid to the miner.
if ( n == 0 )
5 years ago
{
n++;
continue;
}
// Check the pubkeys match the pubkeys in the notarisation.
5 years ago
script = (uint8_t *)&txout.scriptPubKey[0];
scriptlen = (int32_t)txout.scriptPubKey.size();
if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[NotarizationNotaries[n-1]],33) == 0 )
5 years ago
{
// check the value is correct
if ( pblock->vtx[0].vout[n].nValue == AmountToPay )
{
matches++;
total += txout.nValue;
//fprintf(stderr, "MATCHED AmountPaid.%lu notaryid.%i\n",AmountToPay,NotarizationNotaries[n-1]);
}
else fprintf(stderr, "NOT MATCHED AmountPaid.%llu AmountToPay.%llu notaryid.%i\n", (long long)pblock->vtx[0].vout[n].nValue, (long long)AmountToPay, NotarizationNotaries[n-1]);
5 years ago
}
n++;
5 years ago
}
if ( matches != 0 && matches == NotarizationNotaries.size() && totalsats == total )
5 years ago
{
//fprintf(stderr, "Validated coinbase matches notarisation in tx position 1.\n" );
5 years ago
return(totalsats);
}
return(0);
5 years ago
}
bool komodo_appendACscriptpub()
{
static bool didinit = false;
if ( didinit )
return didinit;
if ( ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] == 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] == 51 )
{
CTransaction tx; uint256 blockhash;
// get transaction and check that it occured before height 100.
if ( myGetTransaction(KOMODO_EARLYTXID,tx,blockhash) && mapBlockIndex[blockhash]->GetHeight() < KOMODO_EARLYTXID_HEIGHT )
{
for (int i = 0; i < tx.vout.size(); i++)
{
if ( tx.vout[i].scriptPubKey[0] == OP_RETURN )
{
ASSETCHAINS_SCRIPTPUB.pop_back(); ASSETCHAINS_SCRIPTPUB.pop_back(); // remove last 2 chars.
// get OP_RETURN from txid and append the HexStr of it to scriptpub
5 years ago
ASSETCHAINS_SCRIPTPUB.append(HexStr(tx.vout[i].scriptPubKey.begin()+3, tx.vout[i].scriptPubKey.end()));
//fprintf(stderr, "ac_script.%s\n",ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
return true;
}
}
}
fprintf(stderr, "could not get KOMODO_EARLYTXID.%s OP_RETURN data. Restart with correct txid!\n", KOMODO_EARLYTXID.GetHex().c_str());
StartShutdown();
}
return false;
}
void GetKomodoEarlytxidScriptPub()
{
if ( KOMODO_EARLYTXID == zeroid )
{
fprintf(stderr, "Restart deamon with -earlytxid.\n");
StartShutdown();
return;
}
if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && HUSH_SNAPSHOT_INTERVAL == 0 )
{
fprintf(stderr, "Prices->paymentsCC contract must have -ac_snapshot enabled to pay out.\n");
StartShutdown();
return;
}
if ( chainActive.Height() < KOMODO_EARLYTXID_HEIGHT )
{
fprintf(stderr, "Cannot fetch -earlytxid before block %d.\n",KOMODO_EARLYTXID_HEIGHT);
StartShutdown();
return;
}
CTransaction tx; uint256 blockhash; int32_t i;
// get transaction and check that it occured before height 100.
if ( myGetTransaction(KOMODO_EARLYTXID,tx,blockhash) && mapBlockIndex[blockhash]->GetHeight() < KOMODO_EARLYTXID_HEIGHT )
{
for (i = 0; i < tx.vout.size(); i++)
if ( tx.vout[i].scriptPubKey[0] == OP_RETURN )
break;
if ( i < tx.vout.size() )
{
KOMODO_EARLYTXID_SCRIPTPUB = CScript(tx.vout[i].scriptPubKey.begin()+3, tx.vout[i].scriptPubKey.end());
fprintf(stderr, "KOMODO_EARLYTXID_SCRIPTPUB.%s\n", HexStr(KOMODO_EARLYTXID_SCRIPTPUB.begin(),KOMODO_EARLYTXID_SCRIPTPUB.end()).c_str());
return;
}
}
fprintf(stderr, "INVALID -earlytxid, restart daemon with correct txid.\n");
StartShutdown();
}
6 years ago
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
{
if(fDebug)
fprintf(stderr,"%s at height=%d\n",__func__,height);
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0; static bool didinit = false;
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 )
6 years ago
{
checktoshis = the_commission(pblock,height);
5 years ago
if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 )
{
4 years ago
fprintf(stderr,"ERROR: komodo_checkcommission vsize.%d height.%d commission %.8f has checktoshis=%lu <10000 or less than 2 vouts (vouts=%lu)\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN, checktoshis, pblock->vtx[0].vout.size() );
6 years ago
return(-1);
5 years ago
}
else if ( checktoshis != 0 )
6 years ago
{
script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0];
6 years ago
scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size();
if ( fDebug )
5 years ago
{
int32_t i;
for (i=0; i<scriptlen; i++)
fprintf(stderr,"%02x",script[i]);
fprintf(stderr," vout[1] %.8f vs %.8f\n",(double)checktoshis/COIN,(double)pblock->vtx[0].vout[1].nValue/COIN);
}
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
static bool didinit = false;
if ( !didinit && height > KOMODO_EARLYTXID_HEIGHT && KOMODO_EARLYTXID != zeroid && komodo_appendACscriptpub() )
{
fprintf(stderr, "appended CC_op_return to ASSETCHAINS_SCRIPTPUB.%s\n", ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
}
if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) )
{
decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str());
if ( memcmp(scripthex,script,scriptlen) == 0 )
matched = scriptlen;
}
}
else if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) == 0 )
matched = 35;
6 years ago
else if ( scriptlen == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG && memcmp(script+3,ASSETCHAINS_OVERRIDE_PUBKEYHASH,20) == 0 )
matched = 25;
6 years ago
if ( matched == 0 )
{
5 years ago
if ( 0 && ASSETCHAINS_SCRIPTPUB.size() > 1 )
5 years ago
{
int32_t i;
for (i=0; i<ASSETCHAINS_SCRIPTPUB.size(); i++)
fprintf(stderr,"%02x",ASSETCHAINS_SCRIPTPUB[i]);
}
fprintf(stderr," -ac[%d] payment to wrong pubkey scriptlen.%d, scriptpub[%d] checktoshis.%llu\n",(int32_t)ASSETCHAINS_SCRIPTPUB.size(),scriptlen,(int32_t)ASSETCHAINS_SCRIPTPUB.size()/2,(long long)checktoshis);
6 years ago
return(-1);
}
6 years ago
if ( pblock->vtx[0].vout[1].nValue != checktoshis )
{
fprintf(stderr,"ERROR: ht.%d checktoshis %.8f vs actual vout[1] %.8f !!!\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue));
6 years ago
return(-1);
}
}
}
if(fDebug)
fprintf(stderr,"%s checktoshis=%li at height=%d\n",__func__,checktoshis, height);
6 years ago
return(checktoshis);
}
bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0;
int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
{
uint256 hash,merkleroot; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,scriptlen,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev;
6 years ago
if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW == 0 && Params().NetworkIDString() == "regtest" )
KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1;
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
if ( height == 0 )
6 years ago
{
6 years ago
if ( slowflag != 0 )
{
fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget);
6 years ago
return(0);
}
BlockMap::const_iterator it = mapBlockIndex.find(pblock->hashPrevBlock);
if ( it != mapBlockIndex.end() && (pprev= it->second) != 0 )
height = pprev->GetHeight() + 1;
6 years ago
if ( height == 0 )
return(0);
6 years ago
}
//if ( ASSETCHAINS_ADAPTIVEPOW > 0 )
// bnTarget = komodo_adaptivepow_target(height,bnTarget,pblock->nTime);
if ( ASSETCHAINS_LWMAPOS != 0 && bhash > bnTarget )
{
}
if ( (SMART_CHAIN_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget )
{
failed = 1;
if ( height > 0 && SMART_CHAIN_SYMBOL[0] == 0 ) // for the fast case
{
if ( (n= hush_notaries(pubkeys,height,pblock->nTime)) > 0 )
{
for (i=0; i<n; i++)
if ( memcmp(pubkey33,pubkeys[i],33) == 0 )
{
notaryid = i;
break;
}
}
}
else if ( possible == 0 || SMART_CHAIN_SYMBOL[0] != 0 )
6 years ago
{
6 years ago
if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW )
6 years ago
return(0);
6 years ago
if ( ASSETCHAINS_STAKED == 0 ) // komodo_is_PoSblock will check bnTarget for staked chains
return(-1);
6 years ago
}
}
5 years ago
//fprintf(stderr,"ASSETCHAINS_STAKED.%d ht.%d\n",(int32_t)ASSETCHAINS_STAKED,height);
if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW
{
if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 )
{
6 years ago
if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target
return(0);
6 years ago
if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64
return(-1);
else
{
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
if ( bhash > bnTarget && height > 100 )
{
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);
}
else
{
failed = 0;
CBlockIndex *pindex;
BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash());
pindex = it != mapBlockIndex.end() ? it->second : NULL;
if ( pindex != 0 && pindex->segid == -2 ) {
pindex->segid = -1;
5 years ago
//fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid);
}
}
}
}
else if ( is_PoSblock < 0 )
{
fprintf(stderr,"unexpected negative is_PoSblock.%d\n",is_PoSblock);
return(-1);
}
6 years ago
else if ( ASSETCHAINS_STAKED != 0 )
failed = 0;
}
if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 )
{
if ( height == 1 )
{
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 )
{
int32_t scriptlen; uint8_t scripthex[10000];
script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0];
scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size();
if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) )
{
decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str());
if ( memcmp(scripthex,script,scriptlen) != 0 )
return(-1);
} else return(-1);
}
else if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{
script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0];
5 years ago
scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size();
if ( scriptlen != 35 || script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 )
return(-1);
6 years ago
}
}
else
{
if ( komodo_checkcommission(pblock,height) < 0 )
return(-1);
}
}
// Consensus rule to force miners to mine the notary coinbase payment happens in ConnectBlock
// the default daemon miner, checks the actual vins so the only way this will fail, is if someone changes the miner,
// and then creates txs to the crypto address meeting min sigs and puts it in tx position 1.
// If they go through this effort, the block will still fail at connect block, and will be auto purged by the temp file fix.
if ( failed == 0 && ASSETCHAINS_NOTARY_PAY[0] != 0 && pblock->vtx.size() > 1 )
5 years ago
{
// We check the full validation in ConnectBlock directly to get the amount for coinbase. So just approx here.
if ( slowflag == 0 && pblock->vtx[0].vout.size() > 1 )
5 years ago
{
// Check the notarisation tx is to the crypto address.
5 years ago
if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 )
{
fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height);
return(-1);
5 years ago
}
// Check min sigs.
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
numSN = hush_notaries(notarypubkeys, height, pblock->nTime);
if ( pblock->vtx[1].vin.size() < numSN/5 )
5 years ago
{
5 years ago
fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%lld\n",height,numSN/5,(long long)pblock->vtx[1].vin.size());
return(-1);
5 years ago
}
}
}
6 years ago
//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
6 years ago
if ( failed != 0 && possible == 0 && notaryid < 0 )
return(-1);
else return(0);
}
6 years ago
int32_t komodo_acpublic(uint32_t tiptime)
{
6 years ago
int32_t acpublic = ASSETCHAINS_PUBLIC; CBlockIndex *pindex;
6 years ago
if ( acpublic == 0 )
{
if ( tiptime == 0 )
{
if ( (pindex= chainActive.LastTip()) != 0 )
tiptime = pindex->nTime;
}
if ( (SMART_CHAIN_SYMBOL[0] == 0 || strcmp(SMART_CHAIN_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE )
6 years ago
acpublic = 1;
}
return(acpublic);
}
int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock)
6 years ago
{
CTxDestination address; int32_t i,j,m,n,vout; uint8_t *script; uint256 txid,hashBlock; int64_t zfunds=0,vinsum=0,voutsum=0,sproutfunds=0;
6 years ago
n = pblock->vtx.size();
for (i=0; i<n; i++)
{
6 years ago
CTransaction vintx,&tx = pblock->vtx[i];
6 years ago
if ( (m= tx.vin.size()) > 0 )
{
for (j=0; j<m; j++)
{
if ( i == 0 )
continue;
txid = tx.vin[j].prevout.hash;
vout = tx.vin[j].prevout.n;
if ( !GetTransaction(txid,vintx,hashBlock, false) || vout >= vintx.vout.size() )
{
fprintf(stderr,"ERROR: %s/v%d cant find\n",txid.ToString().c_str(),vout);
return(0);
}
vinsum += vintx.vout[vout].nValue;
}
}
if ( (m= tx.vout.size()) > 0 )
{
for (j=0; j<m-1; j++)
{
if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 )
voutsum += tx.vout[j].nValue;
6 years ago
else printf("skip %.8f -> %s\n",dstr(tx.vout[j].nValue),CBitcoinAddress(address).ToString().c_str());
}
script = (uint8_t *)&tx.vout[j].scriptPubKey[0];
6 years ago
if ( script == 0 || script[0] != 0x6a )
{
if ( ExtractDestination(tx.vout[j].scriptPubKey,address) != 0 && strcmp("RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY",CBitcoinAddress(address).ToString().c_str()) != 0 )
voutsum += tx.vout[j].nValue;
}
6 years ago
}
6 years ago
BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit)
{
zfunds -= joinsplit.vpub_new;
zfunds += joinsplit.vpub_old;
sproutfunds -= joinsplit.vpub_new;
sproutfunds += joinsplit.vpub_old;
6 years ago
}
zfunds -= tx.valueBalance;
6 years ago
}
6 years ago
*zfundsp = zfunds;
*sproutfundsp = sproutfunds;
if ( SMART_CHAIN_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times
6 years ago
return(3 * SATOSHIDEN);
//if ( voutsum-vinsum+zfunds > 100000*SATOSHIDEN || voutsum-vinsum+zfunds < 0 )
//. fprintf(stderr,"ht.%d vins %.8f, vouts %.8f -> %.8f zfunds %.8f\n",nHeight,dstr(vinsum),dstr(voutsum),dstr(voutsum)-dstr(vinsum),dstr(zfunds));
6 years ago
return(voutsum - vinsum);
}
6 years ago
int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height)
6 years ago
{
6 years ago
CBlockIndex *pindex; CBlock block; int64_t zfunds=0,sproutfunds=0,supply = 0;
6 years ago
//fprintf(stderr,"coinsupply %d\n",height);
6 years ago
*zfundsp = *sproutfundsp = 0;
6 years ago
if ( (pindex= komodo_chainactive(height)) != 0 )
{
while ( pindex != 0 && pindex->GetHeight() > 0 )
6 years ago
{
6 years ago
if ( pindex->newcoins == 0 && pindex->zfunds == 0 )
6 years ago
{
if ( komodo_blockload(block,pindex) == 0 )
6 years ago
pindex->newcoins = komodo_newcoins(&pindex->zfunds,&pindex->sproutfunds,pindex->GetHeight(),&block);
6 years ago
else
{
fprintf(stderr,"error loading block.%d\n",pindex->GetHeight());
6 years ago
return(0);
}
6 years ago
}
supply += pindex->newcoins;
6 years ago
zfunds += pindex->zfunds;
6 years ago
sproutfunds += pindex->sproutfunds;
//printf("start ht.%d new %.8f -> supply %.8f zfunds %.8f -> %.8f\n",pindex->GetHeight(),dstr(pindex->newcoins),dstr(supply),dstr(pindex->zfunds),dstr(zfunds));
6 years ago
pindex = pindex->pprev;
6 years ago
}
6 years ago
}
6 years ago
*zfundsp = zfunds;
6 years ago
*sproutfundsp = sproutfunds;
6 years ago
return(supply);
}
struct komodo_staking
{
char address[64];
uint256 txid;
arith_uint256 hashval;
uint64_t nValue;
uint32_t segid32,txtime;
int32_t vout;
CScript scriptPubKey;
};
struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numkp,int32_t *maxkp,uint32_t txtime,uint64_t nValue,uint256 txid,int32_t vout,char *address,uint8_t *hashbuf,CScript pk)
{
uint256 hash; uint32_t segid32; struct komodo_staking *kp;
segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
if ( *numkp >= *maxkp )
{
*maxkp += 1000;
array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp));
//fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array);
}
kp = &array[(*numkp)++];
//fprintf(stderr,"kp.%p num.%d\n",kp,*numkp);
memset(kp,0,sizeof(*kp));
strcpy(kp->address,address);
kp->txid = txid;
kp->vout = vout;
kp->hashval = UintToArith256(hash);
kp->txtime = txtime;
kp->segid32 = segid32;
kp->nValue = nValue;
kp->scriptPubKey = pk;
return(array);
}