From 1cf0648019b446542ac724cf65dd4f9ecfcb788e Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 5 May 2021 12:08:26 -0500 Subject: [PATCH 01/58] add comments --- src/Makefile.ktest.include | 3 ++- src/komodo.h | 41 +++++++++++++++++++++++++++---- src/komodo_bitcoind.h | 4 +-- src/komodo_events.h | 8 ++++++ src/komodo_gateway.h | 26 +++++++++++++++++++- src/test-komodo/test_events.cpp | 43 +++++++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 src/test-komodo/test_events.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index bfbccc196ad..fd4de67cc20 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -14,7 +14,8 @@ komodo_test_SOURCES = \ test-komodo/test_sha256_crypto.cpp \ test-komodo/test_script_standard_tests.cpp \ test-komodo/test_addrman.cpp \ - test-komodo/test_netbase_tests.cpp + test-komodo/test_netbase_tests.cpp \ + test-komodo/test_events.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/komodo.h b/src/komodo.h index 88e741df7f7..e022fb6b702 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -215,6 +215,15 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char } else return(-1); } +/**** + * Read a section of memory + * @param dest the destination + * @param size the size to read + * @param filedata the memory + * @param fposp the position to read from + * @param datalen the size of filedata + * @returns the number of bytes read or -1 on error + */ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen) { if ( *fposp+size <= datalen ) @@ -226,21 +235,43 @@ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datal return(-1); } +/**** + * Parse file to get komodo events + * @param sp the state (stores the events) + * @param filedata the data to parse + * @param fposp the file position + * @param datalen the length of filedata + * @param symbol the currency symbol + * @param dest + * @returns the record type parsed, or -1 on error + */ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) { static int32_t errs; - int32_t func= -1,ht,notarized_height,MoMdepth,num,matched=0; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; long fpos = *fposp; + int32_t func= -1; + int32_t ht; // height + int32_t notarized_height; + int32_t MoMdepth; + int32_t num; + int32_t matched=0; + uint256 MoM; + uint256 notarized_hash; + uint256 notarized_desttxid; + uint8_t pubkeys[64][33]; + long fpos = *fposp; + if ( fpos < datalen ) { func = filedata[fpos++]; if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) matched = 1; - else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) + else + matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) // get height errs++; - if ( func == 'P' ) + if ( func == 'P' ) // pubkey record { - if ( (num= filedata[fpos++]) <= 64 ) + if ( (num= filedata[fpos++]) <= 64 ) // number of keys in this record { if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) errs++; diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index ec9f7cd8503..2e5934cbbc7 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -886,7 +886,7 @@ int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) if ( block->vtx[0].vout.size() > 0 ) { txnouttype whichType; - vector> vch = vector>(); + std::vector> vch = std::vector>(); if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY) { CPubKey pubKey(vch[0]); @@ -2663,7 +2663,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt { static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; int32_t PoSperc = 0, newStakerActive; - set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; + std::set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; uint64_t cbPerc = *utxovaluep, tocoinbase = 0; if (!EnsureWalletIsAvailable(0)) return 0; diff --git a/src/komodo_events.h b/src/komodo_events.h index 5500a341eb2..7a01d464cd8 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -63,6 +63,14 @@ void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t heig } } +/**** + * Add a pubkey event to state + * @param sp the state + * @param symbol the symbol + * @param height + * @param num + * @param pubkeys + */ void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]) { struct komodo_event_pubkeys P; diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 318df7b15b3..68004a8e122 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1259,6 +1259,14 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ else if ( func == 'R' ) // opreturn:*/ } +/**** + * Load file contents into buffer + * @param fname the filename + * @param bufp the buffer that will contain the file contents + * @param lenp the length of the file + * @param allocsizep the buffer size allocated + * @returns the file contents + */ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) { FILE *fp; @@ -1297,9 +1305,17 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) return(buf); } +/*** + * Get file contents + * @param allocsizep the size allocated for the file contents (NOTE: this will probably be 64 bytes larger than the file size) + * @param fname the file name + * @returns the data from the file + */ uint8_t *OS_fileptr(long *allocsizep,char *fname) { - long filesize = 0; uint8_t *buf = 0; void *retptr; + long filesize = 0; // the size of the file + uint8_t *buf = 0; // a pointer to the buffer + void *retptr; // the return pointer (points to buf) *allocsizep = 0; retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); return((uint8_t *)retptr); @@ -1369,6 +1385,14 @@ long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long return(newfpos); } +/*** + * Initialize state from the filesystem + * @param sp the state to initialize + * @param fname the filename + * @param symbol + * @param dest + * @returns -1 on error, 1 on success + */ int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest) { FILE *indfp; char indfname[1024]; uint8_t *filedata; long validated=-1,datalen,fpos,lastfpos; uint32_t tmp,prevpos100,indcounter,starttime; int32_t func,finished = 0; diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp new file mode 100644 index 00000000000..6e17bf53b1e --- /dev/null +++ b/src/test-komodo/test_events.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +//#define KOMODO_ZCASH +//#include + +struct komodo_state; +int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest); +struct komodo_state *komodo_stateptrget(char *base); + +namespace TestEvents { + +TEST(TestEvents, komodo_faststateinit_test) +{ + // create a binary file that should be readable by komodo + boost::filesystem::path temp = boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + const std::string temp_filename = temp.native() + "/kstate.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + // a pubkey record with 2 keys + char data[1+4+1+(33*2)] = {'P', 1, 0, 0, 0, 2}; // public key record identifier with height of 1 plus number of keys plus keys themselves + memset(&data[6], 1, 33); // 1st key is all 1s + memset(&data[39], 2, 33); // 2nd key is all 2s + std::fwrite(data, sizeof(data), 1, fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "KMD"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = nullptr; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); +} + +} // namespace TestEvents \ No newline at end of file From 6410e7963ca3e753885e2f38a7cb6fbe64e8eb31 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 7 May 2021 10:11:05 -0500 Subject: [PATCH 02/58] use std::mutex for komodo_mutex --- src/komodo_events.h | 3 +-- src/komodo_gateway.h | 63 ++++++++++++++++++++++++++------------------ src/komodo_globals.h | 5 ++-- src/komodo_notary.h | 35 ++++++++++++------------ src/komodo_pax.h | 9 ++----- 5 files changed, 60 insertions(+), 55 deletions(-) diff --git a/src/komodo_events.h b/src/komodo_events.h index 7a01d464cd8..178ad04c27d 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -22,7 +22,7 @@ struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char struct komodo_event *ep=0; uint16_t len = (uint16_t)(sizeof(*ep) + datalen); if ( sp != 0 && ASSETCHAINS_SYMBOL[0] != 0 ) { - portable_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); ep = (struct komodo_event *)calloc(1,len); ep->len = len; ep->height = height; @@ -32,7 +32,6 @@ struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char memcpy(ep->space,data,datalen); sp->Komodo_events = (struct komodo_event **)realloc(sp->Komodo_events,(1 + sp->Komodo_numevents) * sizeof(*sp->Komodo_events)); sp->Komodo_events[sp->Komodo_numevents++] = ep; - portable_mutex_unlock(&komodo_mutex); } return(ep); } diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 68004a8e122..450ffa6b5c6 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -66,10 +66,9 @@ void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type) struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type) { struct pax_transaction *pax; uint8_t buf[35]; - pthread_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); pax_keyset(buf,txid,vout,type); HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - pthread_mutex_unlock(&komodo_mutex); return(pax); } @@ -85,7 +84,7 @@ struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout) struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout,uint8_t type,int32_t mark) { struct pax_transaction *pax; uint8_t buf[35]; - pthread_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); pax_keyset(buf,txid,vout,type); HASH_FIND(hh,PAX,buf,sizeof(buf),pax); if ( pax == 0 ) @@ -105,16 +104,14 @@ struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); } - pthread_mutex_unlock(&komodo_mutex); return(pax); } void komodo_paxdelete(struct pax_transaction *pax) { return; // breaks when out of order - pthread_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); HASH_DELETE(hh,PAX,pax); - pthread_mutex_unlock(&komodo_mutex); } void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context @@ -125,26 +122,27 @@ void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t //if ( strcmp(symbol,ASSETCHAINS_SYMBOL) != 0 ) // return; sp = komodo_stateptr(str,dest); - pthread_mutex_lock(&komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - if ( pax == 0 ) { - pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); - pax->txid = txid; - pax->vout = vout; - pax->type = type; - memcpy(pax->buf,buf,sizeof(pax->buf)); - HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); - addflag = 1; - if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - { - int32_t i; for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&txid)[i]); - printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source); + std::lock_guard lock(komodo_mutex); + pax_keyset(buf,txid,vout,type); + HASH_FIND(hh,PAX,buf,sizeof(buf),pax); + if ( pax == 0 ) + { + pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); + pax->txid = txid; + pax->vout = vout; + pax->type = type; + memcpy(pax->buf,buf,sizeof(pax->buf)); + HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); + addflag = 1; + if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + { + int32_t i; for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&txid)[i]); + printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source); + } } } - pthread_mutex_unlock(&komodo_mutex); if ( coinaddr != 0 ) { strcpy(pax->coinaddr,coinaddr); @@ -1395,10 +1393,23 @@ long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long */ int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest) { - FILE *indfp; char indfname[1024]; uint8_t *filedata; long validated=-1,datalen,fpos,lastfpos; uint32_t tmp,prevpos100,indcounter,starttime; int32_t func,finished = 0; - starttime = (uint32_t)time(NULL); - safecopy(indfname,fname,sizeof(indfname)-4); + FILE *indfp; // an index file that will be created + char indfname[1024]; // the filename of the index file + uint8_t *filedata; // data read from the file fname + long validated=-1; // not used + long datalen; // length of the data read from fname plus a little more + long fpos; // where we are reading in filedata + long lastfpos; // not used + uint32_t tmp; // not used + uint32_t prevpos100; // position to be written in index file + uint32_t indcounter; // position within index file + uint32_t starttime = (uint32_t)time(NULL); + int32_t func; // record type + int32_t finished = 0; // boolean, true if file has been read successfully + + safecopy(indfname,fname,sizeof(indfname)-4); // truncate 4 characters from filename strcat(indfname,".ind"); + if ( (filedata= OS_fileptr(&datalen,fname)) != 0 ) { if ( 1 )//datalen >= (1LL << 32) || GetArg("-genind",0) != 0 || (validated= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 063364230e5..98bd369a53a 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once #include "komodo_defs.h" void komodo_prefetch(FILE *fp); @@ -31,7 +31,8 @@ uint64_t komodo_maxallowed(int32_t baseid); int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); -pthread_mutex_t komodo_mutex,staked_mutex; +std::mutex komodo_mutex; +pthread_mutex_t staked_mutex; #define KOMODO_ELECTION_GAP 2000 //((ASSETCHAINS_SYMBOL[0] == 0) ? 2000 : 100) #define KOMODO_ASSETCHAIN_MAXLEN 65 diff --git a/src/komodo_notary.h b/src/komodo_notary.h index f820e0bd568..f001bcac277 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -149,19 +149,20 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam komodo_init(height); //printf("Pubkeys.%p htind.%d vs max.%d\n",Pubkeys,htind,KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP); } - pthread_mutex_lock(&komodo_mutex); - n = Pubkeys[htind].numnotaries; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"%s height.%d t.%u genesis.%d\n",ASSETCHAINS_SYMBOL,height,timestamp,n); - HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) { - if ( kp->notaryid < n ) + std::lock_guard lock(komodo_mutex); + n = Pubkeys[htind].numnotaries; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"%s height.%d t.%u genesis.%d\n",ASSETCHAINS_SYMBOL,height,timestamp,n); + HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) { - mask |= (1LL << kp->notaryid); - memcpy(pubkeys[kp->notaryid],kp->pubkey,33); - } else printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); + if ( kp->notaryid < n ) + { + mask |= (1LL << kp->notaryid); + memcpy(pubkeys[kp->notaryid],kp->pubkey,33); + } else printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); + } } - pthread_mutex_unlock(&komodo_mutex); if ( (n < 64 && mask == ((1LL << n)-1)) || (n == 64 && mask == 0xffffffffffffffffLL) ) return(n); printf("error retrieving notaries ht.%d got mask.%llx for n.%d\n",height,(long long)mask,n); @@ -213,7 +214,7 @@ void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num) htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; //printf("htind.%d activation %d from %d vs %d | hwmheight.%d %s\n",htind,height,origheight,(((origheight+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,hwmheight,ASSETCHAINS_SYMBOL); } else htind = 0; - pthread_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); for (k=0; k hwmheight ) hwmheight = origheight; } @@ -268,9 +268,10 @@ int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33, htind = height / KOMODO_ELECTION_GAP; if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - pthread_mutex_lock(&komodo_mutex); - HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); - pthread_mutex_unlock(&komodo_mutex); + { + std::lock_guard lock(komodo_mutex); + HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); + } if ( kp != 0 ) { if ( (numnotaries= Pubkeys[htind].numnotaries) > 0 ) @@ -469,7 +470,7 @@ void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t not } if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); - portable_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); np = &sp->NPOINTS[sp->NUM_NPOINTS++]; memset(np,0,sizeof(*np)); @@ -479,7 +480,6 @@ void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t not sp->NOTARIZED_DESTTXID = np->notarized_desttxid = notarized_desttxid; sp->MoM = np->MoM = MoM; sp->MoMdepth = np->MoMdepth = MoMdepth; - portable_mutex_unlock(&komodo_mutex); } void komodo_init(int32_t height) @@ -490,7 +490,6 @@ void komodo_init(int32_t height) memset(&zero,0,sizeof(zero)); if ( didinit == 0 ) { - pthread_mutex_init(&komodo_mutex,NULL); decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); if ( height >= 0 ) { diff --git a/src/komodo_pax.h b/src/komodo_pax.h index 9935f34637a..aadebc43bb0 100644 --- a/src/komodo_pax.h +++ b/src/komodo_pax.h @@ -346,12 +346,11 @@ void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals) KMDBTC = ((double)kmdbtc / (1000000000. * 1000.)); BTCUSD = PAX_BTCUSD(height,btcusd); CNYUSD = ((double)cnyusd / 1000000000.); - portable_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36); PVALS[36 * NUM_PRICES] = height; memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35); NUM_PRICES++; - portable_mutex_unlock(&komodo_mutex); if ( 0 ) printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d (%llu %llu %llu)\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES,(long long)kmdbtc,(long long)btcusd,(long long)cnyusd); } @@ -501,7 +500,6 @@ uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,cha height -= 10; if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) { - //portable_mutex_lock(&komodo_mutex); for (i=NUM_PRICES-1; i>=0; i--) { ptr = &PVALS[36 * i]; @@ -513,13 +511,11 @@ uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,cha *kmdbtcp = pvals[MAX_CURRENCIES] / 539; *btcusdp = pvals[MAX_CURRENCIES + 1] / 539; } - //portable_mutex_unlock(&komodo_mutex); if ( kmdbtc != 0 && btcusd != 0 ) return(komodo_paxcalc(height,pvals,baseid,relid,basevolume,kmdbtc,btcusd)); else return(0); } } - //portable_mutex_unlock(&komodo_mutex); } //else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); return(0); } @@ -648,7 +644,7 @@ uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uin return(0); } *seedp = komodo_seed(height); - portable_mutex_lock(&komodo_mutex); + std::lock_guard lock(komodo_mutex); for (i=0; i<17; i++) { if ( (price= komodo_paxpriceB(*seedp,height-i,base,rel,basevolume)) != 0 ) @@ -679,7 +675,6 @@ uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uin if ( height < 165000 || height > 236000 ) break; } - portable_mutex_unlock(&komodo_mutex); if ( nonz != 0 ) sum /= nonz; //printf("-> %lld %s/%s i.%d ht.%d\n",(long long)sum,base,rel,i,height); From 9c42484843a2c18fa1a4c626c3e6f2c9bd73084a Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 7 May 2021 10:12:04 -0500 Subject: [PATCH 03/58] let structs serialize/deserialize themselves --- src/Makefile.am | 1 + src/komodo.h | 83 ++++--- src/komodo_structs.cpp | 75 +++++++ src/komodo_structs.h | 56 ++++- src/test-komodo/test_events.cpp | 373 +++++++++++++++++++++++++++++--- 5 files changed, 528 insertions(+), 60 deletions(-) create mode 100644 src/komodo_structs.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 23cff51cba9..28304d11598 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -482,6 +482,7 @@ libbitcoin_common_a_SOURCES = \ key.cpp \ key_io.cpp \ keystore.cpp \ + komodo_structs.cpp \ netbase.cpp \ metrics.cpp \ primitives/block.cpp \ diff --git a/src/komodo.h b/src/komodo.h index e022fb6b702..f0c9b3d3cfc 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -235,6 +235,7 @@ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datal return(-1); } + /**** * Parse file to get komodo events * @param sp the state (stores the events) @@ -243,55 +244,73 @@ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datal * @param datalen the length of filedata * @param symbol the currency symbol * @param dest - * @returns the record type parsed, or -1 on error + * @returns the record type parsed, or number of errors if negative */ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) { - static int32_t errs; - int32_t func= -1; + int32_t errs = 1; // number of errors found + uint8_t rec_type = 0; // type of record found int32_t ht; // height - int32_t notarized_height; - int32_t MoMdepth; - int32_t num; - int32_t matched=0; - uint256 MoM; - uint256 notarized_hash; - uint256 notarized_desttxid; - uint8_t pubkeys[64][33]; - long fpos = *fposp; + bool symbol_matches = false; + long fpos = *fposp; // current position in data stream if ( fpos < datalen ) { - func = filedata[fpos++]; + rec_type = filedata[fpos++]; if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - matched = 1; + symbol_matches = true; else - matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + symbol_matches = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) // get height errs++; - if ( func == 'P' ) // pubkey record + if ( rec_type == 'P' ) // pubkey record { - if ( (num= filedata[fpos++]) <= 64 ) // number of keys in this record + // while we're doing both old and new way + long temp_pos = fpos; + // old way + int32_t num; + if ( (num = filedata[fpos++]) <= 64 ) // number of keys in this record { + uint8_t pubkeys[64][33]; if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) errs++; else { //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) + if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); } - } else printf("illegal num.%d\n",num); + } + else + printf("illegal number of keys.%d\n",num); + fpos = temp_pos; + // new way + try + { + std::shared_ptr pubkey = std::make_shared(filedata, fpos, datalen, ht); + if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) + sp->add_event(symbol, ht, pubkey); + } + catch(const parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } } - else if ( func == 'N' || func == 'M' ) + else if ( rec_type == 'N' || rec_type == 'M' ) // notary event { + int32_t notarized_height; if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) errs++; + uint256 notarized_hash; if ( memread(¬arized_hash,sizeof(notarized_hash),filedata,&fpos,datalen) != sizeof(notarized_hash) ) errs++; + uint256 notarized_desttxid; if ( memread(¬arized_desttxid,sizeof(notarized_desttxid),filedata,&fpos,datalen) != sizeof(notarized_desttxid) ) errs++; - if ( func == 'M' ) + int32_t MoMdepth; + uint256 MoM; + if ( rec_type == 'M' ) { if ( memread(&MoM,sizeof(MoM),filedata,&fpos,datalen) != sizeof(MoM) ) errs++; @@ -307,7 +326,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); } - else if ( func == 'U' ) // deprecated + else if ( rec_type == 'U' ) // deprecated { uint8_t n,nid; uint256 hash; uint64_t mask; n = filedata[fpos++]; @@ -318,25 +337,25 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long if ( memread(&hash,sizeof(hash),filedata,&fpos,datalen) != sizeof(hash) ) errs++; } - else if ( func == 'K' ) + else if ( rec_type == 'K' ) // kmd event { int32_t kheight; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); } - else if ( func == 'T' ) + else if ( rec_type == 'T' ) // kmd event with timestamp { int32_t kheight,ktimestamp; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; if ( memread(&ktimestamp,sizeof(ktimestamp),filedata,&fpos,datalen) != sizeof(ktimestamp) ) errs++; - //if ( matched != 0 ) global independent states -> inside *sp + //if ( symbol_matches != 0 ) global independent states -> inside *sp //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); } - else if ( func == 'R' ) + else if ( rec_type == 'R' ) // opreturn { uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) @@ -351,7 +370,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long { if ( memread(opret,olen,filedata,&fpos,datalen) != olen ) errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && symbol_matches ) { int32_t i; for (i=0; i global PVALS + //if ( symbol_matches != 0 ) global shared state -> global PVALS //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); } else printf("error loading pvals[%d]\n",numpvals); } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); *fposp = fpos; - return(func); + return(rec_type); } - return(-1); + return -errs; } void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp new file mode 100644 index 00000000000..03c46a1d542 --- /dev/null +++ b/src/komodo_structs.cpp @@ -0,0 +1,75 @@ +#include + +extern std::mutex komodo_mutex; + + +template +std::size_t mem_read(T& dest, uint8_t *filedata, long &fpos, long datalen) +{ + if (fpos + sizeof(T) <= datalen) + { + memcpy( &dest, &filedata[fpos], sizeof(T) ); + fpos += sizeof(T); + return sizeof(T); + } + throw parse_error("Invalid size: " + std::to_string(sizeof(T)) ); +} + +template +std::size_t mem_read(T(&dest)[N], uint8_t *filedata, long& fpos, long datalen) +{ + std::size_t sz = sizeof(T) * N; + if (fpos + sz <= datalen) + { + memcpy( &dest, &filedata[fpos], sz ); + fpos += sz; + return sz; + } + throw parse_error("Invalid size: " + std::to_string( sz ) ); +} + +template +std::size_t mem_nread(T(&dest)[N], size_t num_elements, uint8_t *filedata, long& fpos, long datalen) +{ + std::size_t sz = sizeof(T) * num_elements; + if (fpos + sz <= datalen) + { + memcpy( &dest, &filedata[fpos], sz ); + fpos += sz; + return sz; + } + throw parse_error("Invalid size: " + std::to_string(sz)); +} + +bool komodo_state::add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in) +{ + if (ASSETCHAINS_SYMBOL[0] != 0) + { + std::lock_guard lock(komodo_mutex); + events.push_back( in ); + return true; + } + return false; +} + +/*** + * ctor from data stream + * @param data the data stream + * @param pos the starting position (will advance) + * @param data_len full length of data + */ +komodo_event_pubkeys::komodo_event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t height) : event(KOMODO_EVENT_PUBKEYS, height) +{ + num = data[pos++]; + if (num > 64) + throw parse_error("Illegal number of keys: " + std::to_string(num)); + mem_nread(pubkeys, num, data, pos, data_len); +} + +std::ostream& operator<<(std::ostream& os, const komodo_event_pubkeys& in) +{ + os << in.num; + for(uint8_t i = 0; i < in.num; ++i) + os << in.pubkeys[i]; + return os; +} diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 6b7c316b6b9..b8187c43c13 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once #include "komodo_defs.h" #include "uthash.h" @@ -59,8 +59,55 @@ typedef union _bits320 bits320; struct komodo_kv { UT_hash_handle hh; bits256 pubkey; uint8_t *key,*value; int32_t height; uint32_t flags; uint16_t keylen,valuesize; }; -struct komodo_event_notarized { uint256 blockhash,desttxid,MoM; int32_t notarizedheight,MoMdepth; char dest[16]; }; -struct komodo_event_pubkeys { uint8_t num; uint8_t pubkeys[64][33]; }; +enum komodo_event_type +{ + KOMODO_EVENT_PUBKEYS +}; + +class parse_error : public std::logic_error +{ +public: + parse_error(const std::string& in) : std::logic_error(in) {} +}; + + +struct komodo_event_notarized +{ + uint256 blockhash; + uint256 desttxid; + uint256 MoM; + int32_t notarizedheight; + int32_t MoMdepth; + char dest[16]; +}; + +class event +{ +public: + event(komodo_event_type t, int32_t height) : type(t), height(height) {} + komodo_event_type type; + int32_t height; +}; + +struct komodo_event_pubkeys : public event +{ + /*** + * Default ctor + */ + komodo_event_pubkeys() : event(KOMODO_EVENT_PUBKEYS, 0), num(0) {} + /*** + * ctor from data stream + * @param data the data stream + * @param pos the starting position (will advance) + * @param data_len full length of data + */ + komodo_event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); + uint8_t num; + uint8_t pubkeys[64][33]; +}; + +std::ostream& operator<<(std::ostream& os, const komodo_event_pubkeys& in); + struct komodo_event_opreturn { uint256 txid; uint64_t value; uint16_t vout,oplen; uint8_t opret[]; }; struct komodo_event_pricefeed { uint8_t num; uint32_t prices[35]; }; @@ -124,7 +171,10 @@ struct komodo_state uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; struct notarized_checkpoint *NPOINTS; int32_t NUM_NPOINTS,last_NPOINTSi; struct komodo_event **Komodo_events; int32_t Komodo_numevents; + std::list> events; uint32_t RTbufs[64][3]; uint64_t RTmask; + bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); + }; #endif /* KOMODO_STRUCTS_H */ diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index 6e17bf53b1e..549b57703bf 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -2,42 +2,365 @@ #include #include #include -//#define KOMODO_ZCASH -//#include +#include -struct komodo_state; int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest); struct komodo_state *komodo_stateptrget(char *base); +extern int32_t KOMODO_EXTERNAL_NOTARIES; namespace TestEvents { -TEST(TestEvents, komodo_faststateinit_test) +void write_p_record(std::FILE* fp) { - // create a binary file that should be readable by komodo - boost::filesystem::path temp = boost::filesystem::unique_path(); - boost::filesystem::create_directories(temp); - const std::string temp_filename = temp.native() + "/kstate.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); // a pubkey record with 2 keys - char data[1+4+1+(33*2)] = {'P', 1, 0, 0, 0, 2}; // public key record identifier with height of 1 plus number of keys plus keys themselves + char data[5+1+(33*2)] = {'P', 1, 0, 0, 0, 2}; // public key record identifier with height of 1 plus number of keys plus keys themselves memset(&data[6], 1, 33); // 1st key is all 1s memset(&data[39], 2, 33); // 2nd key is all 2s std::fwrite(data, sizeof(data), 1, fp); - std::fclose(fp); - // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); - // attempt to read the file - char symbol[] = "KMD"; - komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); - char* dest = nullptr; - // attempt to read the file - int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); - // compare results - ASSERT_EQ(result, 1); +} +void write_n_record(std::FILE* fp) +{ + // a notarized record has + // 5 byte header + // 4 bytes notarized_height + // 32 bytes notarized hash( blockhash) + // 32 bytes desttxid + char data[73] = {'N', 1, 0, 0, 0, 2, 0, 0, 0}; + memset(&data[9], 1, 32); // notarized hash + memset(&data[41], 2, 32); // desttxid + std::fwrite(data, sizeof(data), 1, fp); +} +void write_m_record(std::FILE* fp) +{ + // a notarized M record has + // 5 byte header + // 4 bytes notarized_height + // 32 bytes notarized hash( blockhash) + // 32 bytes desttxid + // 32 bytes MoM + // 4 bytes MoMdepth + char data[109] = {'M', 1, 0, 0, 0, 3, 0, 0, 0}; + memset(&data[9], 1, 32); // notarized hash + memset(&data[41], 2, 32); // desttxid + memset(&data[73], 3, 32); // MoM + memset(&data[105], 4, 4); // MoMdepth + std::fwrite(data, sizeof(data), 1, fp); +} +void write_u_record(std::FILE* fp) +{ + // a U record has + // 5 byte header + // 1 byte n and 1 byte nid + // 8 bytes mask + // 32 bytes hash + char data[47] = {'U', 1, 0, 0, 0, 'N', 'I'}; + memset(&data[7], 1, 8); // mask + memset(&data[15], 2, 32); // hash + std::fwrite(data, sizeof(data), 1, fp); +} +void write_k_record(std::FILE* fp) +{ + // a K record has + // 5 byte header + // 4 bytes height + char data[9] = {'K', 1, 0, 0, 0 }; + memset(&data[5], 1, 4); // height + std::fwrite(data, sizeof(data), 1, fp); +} +void write_t_record(std::FILE* fp) +{ + // a T record has + // 5 byte header + // 4 bytes height + // 4 bytes timestamp + char data[13] = {'T', 1, 0, 0, 0 }; + memset(&data[5], 1, 4); // height + memset(&data[9], 2, 4); // timestamp + std::fwrite(data, sizeof(data), 1, fp); +} +void write_r_record(std::FILE* fp) +{ + // an R record has + // 5 byte header + // 32 byte txid + // 2 byte v + // 8 byte ovalue + // 2 byte olen + // olen bytes of data + char data[65583] = {'R', 1, 0, 0, 0 }; + memset(&data[5], 1, 32); // txid + memset(&data[37], 2, 2); // v + memset(&data[39], 3, 8); // ovalue + unsigned char olen[2] = {254, 255}; // 65534 + memcpy(&data[47], olen, 2); + memset(&data[49], 4, 65534); + std::fwrite(data, sizeof(data), 1, fp); +} +void write_v_record(std::FILE* fp) +{ + // a V record has + // 5 byte header + // 1 byte counter + // counter * 4 bytes of data + char data[146] = {'V', 1, 0, 0, 0}; + memset(&data[5], 35, 1); // counter + memset(&data[6], 1, 140); // data + std::fwrite(data, sizeof(data), 1, fp); +} + +/**** + * The main purpose of this test is to verify that + * state files created continue to be readable despite logic + * changes. Files need to be readable. The record format should + * not change without hardfork protection + */ +TEST(TestEvents, komodo_faststateinit_test) +{ + strcpy(ASSETCHAINS_SYMBOL, "TST"); + KOMODO_EXTERNAL_NOTARIES = 1; + + boost::filesystem::path temp = boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + try + { + // NOTE: header contains a 5 byte header that is make up of + // an 8 bit identifier (i.e. 'P', 'N', etc.) + // plus a 32 bit height. Everything else is record specific + // pubkey record + { + // create a binary file that should be readable by komodo + const std::string temp_filename = temp.native() + "/kstate.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_p_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = nullptr; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + // The first and second event should be pub keys + ASSERT_EQ(state->Komodo_numevents, 1); + komodo_event* ev1 = state->Komodo_events[0]; + ASSERT_EQ(ev1->height, 1); + ASSERT_EQ(ev1->type, 'P'); + } + // notarized record + { + const std::string temp_filename = temp.native() + "/notarized.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_n_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 2); + komodo_event* ev = state->Komodo_events[1]; + ASSERT_EQ(ev->height, 1); + ASSERT_EQ(ev->type, 'N'); + } + // notarized M record + { + const std::string temp_filename = temp.native() + "/notarized.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_m_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 3); + komodo_event* ev = state->Komodo_events[2]; + ASSERT_EQ(ev->height, 1); + ASSERT_EQ(ev->type, 'N'); // code converts "M" to "N" + } + // record type "U" (deprecated) + { + const std::string temp_filename = temp.native() + "/type_u.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_u_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 3); // does not get added to state + } + // record type K (KMD height) + { + const std::string temp_filename = temp.native() + "/kmdtype.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_k_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 4); + komodo_event* ev = state->Komodo_events[3]; + ASSERT_EQ(ev->height, 1); + ASSERT_EQ(ev->type, 'K'); + } + // record type T (KMD height with timestamp) + { + const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_t_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 5); + komodo_event* ev = state->Komodo_events[4]; + ASSERT_EQ(ev->height, 1); + ASSERT_EQ(ev->type, 'K'); // changed from T to K + } + // record type R (opreturn) + { + const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_r_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 6); + komodo_event* ev = state->Komodo_events[5]; + ASSERT_EQ(ev->height, 1); + ASSERT_EQ(ev->type, 'R'); + } + // record type V + { + const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_v_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 7); + komodo_event* ev = state->Komodo_events[6]; + ASSERT_EQ(ev->height, 1); + ASSERT_EQ(ev->type, 'V'); + } + // all together in 1 file + { + const std::string temp_filename = temp.native() + "/combined_state.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_p_record(fp); + write_n_record(fp); + write_m_record(fp); + write_u_record(fp); + write_k_record(fp); + write_t_record(fp); + write_r_record(fp); + write_v_record(fp); + std::fclose(fp); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + ASSERT_EQ(state->Komodo_numevents, 14); + komodo_event* ev1 = state->Komodo_events[7]; + ASSERT_EQ(ev1->height, 1); + ASSERT_EQ(ev1->type, 'P'); + } + } + catch(...) + { + FAIL() << "Exception thrown"; + } + boost::filesystem::remove_all(temp); } } // namespace TestEvents \ No newline at end of file From d987d9fc2d2751ca0d01e27489dbd78567b9db5e Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 7 May 2021 17:11:41 -0500 Subject: [PATCH 04/58] refactor events --- src/komodo.h | 76 +++++++++- src/komodo_structs.cpp | 246 ++++++++++++++++++++++++++++++-- src/komodo_structs.h | 114 +++++++++++---- src/test-komodo/test_events.cpp | 105 ++++++++++++++ 4 files changed, 503 insertions(+), 38 deletions(-) diff --git a/src/komodo.h b/src/komodo.h index f0c9b3d3cfc..c25b17bd4cc 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -287,11 +287,11 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long // new way try { - std::shared_ptr pubkey = std::make_shared(filedata, fpos, datalen, ht); + std::shared_ptr pubkey = std::make_shared(filedata, fpos, datalen, ht); if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) sp->add_event(symbol, ht, pubkey); } - catch(const parse_error& pe) + catch(const komodo::parse_error& pe) { printf("%s\n", pe.what()); errs++; @@ -299,6 +299,8 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'N' || rec_type == 'M' ) // notary event { + // old way + long temp_pos = fpos; int32_t notarized_height; if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) errs++; @@ -325,6 +327,18 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long MoMdepth = 0; } komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); + fpos = temp_pos; // reset for new way + // new way + try + { + std::shared_ptr notarized = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'M'); + sp->add_event(symbol, ht, notarized); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } } else if ( rec_type == 'U' ) // deprecated { @@ -339,13 +353,29 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'K' ) // kmd event { + long temp_pos = fpos; + // old way int32_t kheight; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); + komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); + fpos = temp_pos; // reset for new way + // new way + try + { + std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht); + sp->add_event(symbol, ht, kmd_height); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } } else if ( rec_type == 'T' ) // kmd event with timestamp { + long temp_pos = fpos; + // old way int32_t kheight,ktimestamp; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; @@ -354,9 +384,23 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long //if ( symbol_matches != 0 ) global independent states -> inside *sp //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); + fpos = temp_pos; + // new way + try + { + std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'T'); + sp->add_event(symbol, ht, kmd_height); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } } else if ( rec_type == 'R' ) // opreturn { + long temp_pos = fpos; + // old way uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) errs++; @@ -384,6 +428,18 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long filedata[fpos++]; //printf("illegal olen.%u\n",olen); } + fpos = temp_pos; + // new way + try + { + std::shared_ptr opret = std::make_shared(filedata, fpos, datalen, ht); + sp->add_event(symbol, ht, opret); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } } else if ( rec_type == 'D' ) { @@ -391,6 +447,8 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'V' ) // pricefeed { + long temp_pos = fpos; + // old way int32_t numpvals; uint32_t pvals[128]; numpvals = filedata[fpos++]; if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && memread(pvals,(int32_t)(sizeof(uint32_t)*numpvals),filedata,&fpos,datalen) == numpvals*sizeof(uint32_t) ) @@ -400,6 +458,18 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); } else printf("error loading pvals[%d]\n",numpvals); + fpos = temp_pos; + // new way + try + { + std::shared_ptr feed = std::make_shared(filedata, fpos, datalen, ht); + sp->add_event(symbol, ht, feed); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); *fposp = fpos; return(rec_type); diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 03c46a1d542..444a861eb37 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -3,6 +3,73 @@ extern std::mutex komodo_mutex; +/*** + * komodo_state + */ + +bool komodo_state::add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in) +{ + if (ASSETCHAINS_SYMBOL[0] != 0) + { + std::lock_guard lock(komodo_mutex); + events.push_back( in ); + return true; + } + return false; +} + +namespace komodo { + +/*** + * Helps serialize integrals + */ +template +class serializable +{ +public: + serializable(const T& in) : value(in) {} + T value; +}; + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + os << (uint8_t) (in.value & 0x000000ff) + << (uint8_t) ((in.value & 0x0000ff00) >> 8) + << (uint8_t) ((in.value & 0x00ff0000) >> 16) + << (uint8_t) ((in.value & 0xff000000) >> 24); + return os; +} + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + os << (uint8_t) (in.value & 0x00ff) + << (uint8_t) ((in.value & 0xff00) >> 8); + return os; +} + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + in.value.Serialize(os); + return os; +} + +std::ostream& operator<<(std::ostream& os, serializable in) +{ + os << (uint8_t) (in.value & 0x00000000000000ff) + << (uint8_t) ((in.value & 0x000000000000ff00) >> 8) + << (uint8_t) ((in.value & 0x0000000000ff0000) >> 16) + << (uint8_t) ((in.value & 0x00000000ff000000) >> 24) + << (uint8_t) ((in.value & 0x000000ff00000000) >> 32) + << (uint8_t) ((in.value & 0x0000ff0000000000) >> 40) + << (uint8_t) ((in.value & 0x00ff000000000000) >> 48) + << (uint8_t) ((in.value & 0xff00000000000000) >> 56); + return os; +} + +/*** + * Read a chunk of memory + */ + template std::size_t mem_read(T& dest, uint8_t *filedata, long &fpos, long datalen) { @@ -15,6 +82,17 @@ std::size_t mem_read(T& dest, uint8_t *filedata, long &fpos, long datalen) throw parse_error("Invalid size: " + std::to_string(sizeof(T)) ); } +std::size_t mem_readn(void* dest, size_t num_bytes, uint8_t *filedata, long &fpos, long datalen) +{ + if (fpos + num_bytes <= datalen) + { + memcpy(dest, &filedata[fpos], num_bytes ); + fpos += num_bytes; + return num_bytes; + } + throw parse_error("Invalid size: " + std::to_string(num_bytes) ); +} + template std::size_t mem_read(T(&dest)[N], uint8_t *filedata, long& fpos, long datalen) { @@ -28,6 +106,9 @@ std::size_t mem_read(T(&dest)[N], uint8_t *filedata, long& fpos, long datalen) throw parse_error("Invalid size: " + std::to_string( sz ) ); } +/**** + * Read a size that is less than the array length + */ template std::size_t mem_nread(T(&dest)[N], size_t num_elements, uint8_t *filedata, long& fpos, long datalen) { @@ -41,15 +122,50 @@ std::size_t mem_nread(T(&dest)[N], size_t num_elements, uint8_t *filedata, long& throw parse_error("Invalid size: " + std::to_string(sz)); } -bool komodo_state::add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in) + +/**** + * This serializes the 5 byte header of an event + * @param os the stream + * @param in the event + * @returns the stream + */ +std::ostream& operator<<(std::ostream& os, const event& in) { - if (ASSETCHAINS_SYMBOL[0] != 0) + switch (in.type) { - std::lock_guard lock(komodo_mutex); - events.push_back( in ); - return true; + case(EVENT_PUBKEYS): + os << "P"; + break; + case(EVENT_NOTARIZED): + { + event_notarized* tmp = dynamic_cast(const_cast(&in)); + if (tmp->MoMdepth == 0) + os << "N"; + else + os << "M"; + break; + } + case(EVENT_U): + os << "U"; + break; + case(EVENT_KMDHEIGHT): + { + event_kmdheight* tmp = dynamic_cast(const_cast(&in)); + if (tmp->timestamp == 0) + os << "K"; + else + os << "T"; + break; + } + case(EVENT_OPRETURN): + os << "R"; + break; + case(EVENT_PRICEFEED): + os << "V"; + break; } - return false; + os << serializable(in.height); + return os; } /*** @@ -58,7 +174,7 @@ bool komodo_state::add_event(const std::string& symbol, const uint32_t height, s * @param pos the starting position (will advance) * @param data_len full length of data */ -komodo_event_pubkeys::komodo_event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t height) : event(KOMODO_EVENT_PUBKEYS, height) +event_pubkeys::event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t height) : event(EVENT_PUBKEYS, height) { num = data[pos++]; if (num > 64) @@ -66,10 +182,122 @@ komodo_event_pubkeys::komodo_event_pubkeys(uint8_t* data, long& pos, long data_l mem_nread(pubkeys, num, data, pos, data_len); } -std::ostream& operator<<(std::ostream& os, const komodo_event_pubkeys& in) +std::ostream& operator<<(std::ostream& os, const event_pubkeys& in) { + const event& e = dynamic_cast(in); + os << e; os << in.num; - for(uint8_t i = 0; i < in.num; ++i) + for(uint8_t i = 0; i < in.num-1; ++i) os << in.pubkeys[i]; return os; } + +event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, bool includeMoM) : event(EVENT_NOTARIZED, height) +{ + mem_read(this->notarizedheight, data, pos, data_len); + mem_read(this->blockhash, data, pos, data_len); + mem_read(this->desttxid, data, pos, data_len); + if (includeMoM) + { + mem_read(this->MoM, data, pos, data_len); + mem_read(this->MoMdepth, data, pos, data_len); + } +} + +std::ostream& operator<<(std::ostream& os, const event_notarized& in) +{ + const event& e = dynamic_cast(in); + os << e; + os << serializable(in.notarizedheight); + os << serializable(in.blockhash); + os << serializable(in.desttxid); + if (in.MoMdepth > 0) + { + os << serializable(in.MoM); + os << serializable(in.MoMdepth); + } + return os; +} + +event_u::event_u(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_U, height) +{ + mem_read(this->n, data, pos, data_len); + mem_read(this->nid, data, pos, data_len); + mem_read(this->mask, data, pos, data_len); + mem_read(this->hash, data, pos, data_len); +} + +std::ostream& operator<<(std::ostream& os, const event_u& in) +{ + const event& e = dynamic_cast(in); + os << e; + os << in.n << in.nid; + os.write((const char*)in.mask, 8); + os.write((const char*)in.hash, 32); + return os; +} + +event_kmdheight::event_kmdheight(uint8_t* data, long &pos, long data_len, int32_t height, bool includeTimestamp) : event(EVENT_KMDHEIGHT, height) +{ + mem_read(this->kheight, data, pos, data_len); + if (includeTimestamp) + mem_read(this->timestamp, data, pos, data_len); +} + +std::ostream& operator<<(std::ostream& os, const event_kmdheight& in) +{ + const event& e = dynamic_cast(in); + os << e << serializable(in.kheight); + if (in.timestamp > 0) + os << serializable(in.timestamp); + return os; +} + +event_opreturn::event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_OPRETURN, height) +{ + mem_read(this->txid, data, pos, data_len); + mem_read(this->value, data, pos, data_len); + mem_read(this->vout, data, pos, data_len); + mem_read(this->oplen, data, pos, data_len); + this->opret = new uint8_t[this->oplen]; + mem_readn(this->opret, this->oplen, data, pos, data_len); +} + +event_opreturn::~event_opreturn() +{ + if (opret != nullptr) + delete[] opret; +} + +std::ostream& operator<<(std::ostream& os, const event_opreturn& in) +{ + const event& e = dynamic_cast(in); + os << e + << serializable(in.txid) + << serializable(in.value) + << serializable(in.vout) + << serializable(in.oplen); + os.write( (const char*)in.opret, in.oplen); + return os; +} + +event_pricefeed::event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_PRICEFEED, height) +{ + mem_read(this->num, data, pos, data_len); + // we're only interested if there are 35 prices. + // If there is any other amount, advance the pointer, but don't save it + if (this->num == 35) + mem_nread(this->prices, this->num, data, pos, data_len); + else + pos += num * sizeof(uint32_t); +} + +std::ostream& operator<<(std::ostream& os, const event_pricefeed& in) +{ + const event& e = dynamic_cast(in); + os << e << (uint8_t)in.num; + os.write((const char*)in.prices, in.num * sizeof(uint32_t)); + return os; +} + +} // namespace komodo \ No newline at end of file diff --git a/src/komodo_structs.h b/src/komodo_structs.h index b8187c43c13..da38fc7d3c4 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -13,6 +13,10 @@ * * ******************************************************************************/ #pragma once +#include +#include +#include + #include "komodo_defs.h" #include "uthash.h" @@ -57,11 +61,34 @@ union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; typedef union _bits320 bits320; +// structs prior to refactor struct komodo_kv { UT_hash_handle hh; bits256 pubkey; uint8_t *key,*value; int32_t height; uint32_t flags; uint16_t keylen,valuesize; }; +struct komodo_event_notarized { uint256 blockhash,desttxid,MoM; int32_t notarizedheight,MoMdepth; char dest[16]; }; +struct komodo_event_pubkeys { uint8_t num; uint8_t pubkeys[64][33]; }; +struct komodo_event_opreturn { uint256 txid; uint64_t value; uint16_t vout,oplen; uint8_t opret[]; }; +struct komodo_event_pricefeed { uint8_t num; uint32_t prices[35]; }; + +struct komodo_event +{ + struct komodo_event *related; + uint16_t len; + int32_t height; + uint8_t type,reorged; + char symbol[KOMODO_ASSETCHAIN_MAXLEN]; + uint8_t space[]; +}; + +namespace komodo { + enum komodo_event_type { - KOMODO_EVENT_PUBKEYS + EVENT_PUBKEYS, + EVENT_NOTARIZED, + EVENT_U, + EVENT_KMDHEIGHT, + EVENT_OPRETURN, + EVENT_PRICEFEED }; class parse_error : public std::logic_error @@ -70,9 +97,21 @@ class parse_error : public std::logic_error parse_error(const std::string& in) : std::logic_error(in) {} }; +class event +{ +public: + event(komodo_event_type t, int32_t height) : type(t), height(height) {} + virtual ~event() = default; + komodo_event_type type; + int32_t height; +}; +std::ostream& operator<<(std::ostream& os, const event& in); -struct komodo_event_notarized -{ + +struct event_notarized : public event +{ + event_notarized() : event(komodo_event_type::EVENT_NOTARIZED, 0), notarizedheight(0), MoMdepth(0) {} + event_notarized(uint8_t* data, long &pos, long data_len, int32_t height, bool includeMoM = false); uint256 blockhash; uint256 desttxid; uint256 MoM; @@ -80,46 +119,69 @@ struct komodo_event_notarized int32_t MoMdepth; char dest[16]; }; +std::ostream& operator<<(std::ostream& os, const event_notarized& in); -class event -{ -public: - event(komodo_event_type t, int32_t height) : type(t), height(height) {} - komodo_event_type type; - int32_t height; -}; - -struct komodo_event_pubkeys : public event +struct event_pubkeys : public event { /*** * Default ctor */ - komodo_event_pubkeys() : event(KOMODO_EVENT_PUBKEYS, 0), num(0) {} + event_pubkeys() : event(EVENT_PUBKEYS, 0), num(0) {} /*** * ctor from data stream * @param data the data stream * @param pos the starting position (will advance) * @param data_len full length of data */ - komodo_event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); + event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); uint8_t num; uint8_t pubkeys[64][33]; }; +std::ostream& operator<<(std::ostream& os, const event_pubkeys& in); -std::ostream& operator<<(std::ostream& os, const komodo_event_pubkeys& in); +struct event_u : public event +{ + event_u() : event(EVENT_U, 0) {} + event_u(uint8_t *data, long &pos, long data_len, int32_t height); + uint8_t n; + uint8_t nid; + uint8_t mask[8]; + uint8_t hash[32]; +}; +std::ostream& operator<<(std::ostream& os, const event_u& in); -struct komodo_event_opreturn { uint256 txid; uint64_t value; uint16_t vout,oplen; uint8_t opret[]; }; -struct komodo_event_pricefeed { uint8_t num; uint32_t prices[35]; }; +struct event_kmdheight : public event +{ + event_kmdheight() : event(EVENT_KMDHEIGHT, 0) {} + event_kmdheight(uint8_t *data, long &pos, long data_len, int32_t height, bool includeTimestamp = false); + int32_t kheight = 0; + uint32_t timestamp = 0; +}; +std::ostream& operator<<(std::ostream& os, const event_kmdheight& in); -struct komodo_event +struct event_opreturn : public event +{ + event_opreturn() : event(EVENT_OPRETURN, 0) {} + event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height); + ~event_opreturn(); + uint256 txid; + uint64_t value; + uint16_t vout; + uint16_t oplen; + uint8_t *opret = nullptr; +}; +std::ostream& operator<<(std::ostream& os, const event_opreturn& in); + +struct event_pricefeed : public event { - struct komodo_event *related; - uint16_t len; - int32_t height; - uint8_t type,reorged; - char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - uint8_t space[]; + event_pricefeed() : event(EVENT_PRICEFEED, 0) {} + event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height); + uint8_t num; + uint32_t prices[35]; }; +std::ostream& operator<<(std::ostream& os, const event_pricefeed& in); + +} // namespace komodo struct pax_transaction { @@ -171,9 +233,9 @@ struct komodo_state uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; struct notarized_checkpoint *NPOINTS; int32_t NUM_NPOINTS,last_NPOINTSi; struct komodo_event **Komodo_events; int32_t Komodo_numevents; - std::list> events; + std::list> events; uint32_t RTbufs[64][3]; uint64_t RTmask; - bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); + bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); }; diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index 549b57703bf..1a9d6987d90 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,39 @@ void write_v_record(std::FILE* fp) memset(&data[6], 1, 140); // data std::fwrite(data, sizeof(data), 1, fp); } +template +bool compare_serialization(const std::string& filename, std::shared_ptr in) +{ + // read contents of file + std::ifstream s(filename, std::ios::binary); + std::vector file_contents((std::istreambuf_iterator(s)), std::istreambuf_iterator()); + // get contents of in + std::stringstream ss; + ss << *(in.get()); + std::vector in_contents( (std::istreambuf_iterator(ss)), std::istreambuf_iterator()); + bool retval = file_contents == in_contents; + if (!retval) + { + if (file_contents.size() != in_contents.size()) + { + std::cout << "File has " << std::to_string( file_contents.size() ) << " bytes but serialized data has " << in_contents.size() << "\n"; + } + else + { + for(size_t i = 0; i < file_contents.size(); ++i) + { + if (file_contents[i] != in_contents[i]) + { + std::cout << "Difference at position " << std::to_string(i) + << " " << std::hex << std::setfill('0') << std::setw(2) << (int)file_contents[i] + << " " << std::hex << std::setfill('0') << std::setw(2) << (int)in_contents[i] << "\n"; + break; + } + } + } + } + return retval; +} /**** * The main purpose of this test is to verify that @@ -152,6 +186,13 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev1 = state->Komodo_events[0]; ASSERT_EQ(ev1->height, 1); ASSERT_EQ(ev1->type, 'P'); + // check that the new way is the same + ASSERT_EQ(state->events.size(), 1); + std::shared_ptr ev2 = std::dynamic_pointer_cast(state->events.front()); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PUBKEYS); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // notarized record { @@ -177,6 +218,13 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev = state->Komodo_events[1]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'N'); + // check that the new way is the same + ASSERT_EQ(state->events.size(), 2); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(++state->events.begin()) ); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // notarized M record { @@ -202,6 +250,15 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev = state->Komodo_events[2]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'N'); // code converts "M" to "N" + // check that the new way is the same + ASSERT_EQ(state->events.size(), 3); + auto itr = state->events.begin(); + std::advance(itr, 2); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // record type "U" (deprecated) { @@ -224,6 +281,18 @@ TEST(TestEvents, komodo_faststateinit_test) // compare results ASSERT_EQ(result, 1); ASSERT_EQ(state->Komodo_numevents, 3); // does not get added to state + // check that the new way is the same + ASSERT_EQ(state->events.size(), 3); + auto itr = state->events.begin(); + // this does not get added to state, so we need to serialize the object just + // to verify serialization works as expected + std::shared_ptr ev2 = std::make_shared(); + ev2->height = 1; + ev2->n = 'N'; + ev2->nid = 'I'; + memset(ev2->mask, 1, 8); + memset(ev2->hash, 2, 32); + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // record type K (KMD height) { @@ -249,6 +318,15 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev = state->Komodo_events[3]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'K'); + // check that the new way is the same + ASSERT_EQ(state->events.size(), 4); + auto itr = state->events.begin(); + std::advance(itr, 3); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // record type T (KMD height with timestamp) { @@ -274,6 +352,15 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev = state->Komodo_events[4]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'K'); // changed from T to K + // check that the new way is the same + ASSERT_EQ(state->events.size(), 5); + auto itr = state->events.begin(); + std::advance(itr, 4); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // record type R (opreturn) { @@ -299,6 +386,15 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev = state->Komodo_events[5]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'R'); + // check that the new way is the same + ASSERT_EQ(state->events.size(), 6); + auto itr = state->events.begin(); + std::advance(itr, 5); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_OPRETURN); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // record type V { @@ -324,6 +420,15 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev = state->Komodo_events[6]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'V'); + // check that the new way is the same + ASSERT_EQ(state->events.size(), 7); + auto itr = state->events.begin(); + std::advance(itr, 6); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PRICEFEED); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); } // all together in 1 file { From 0c23dee238e4311918c3926dbcae85af15ba7141 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 7 May 2021 17:45:51 -0500 Subject: [PATCH 05/58] test 1 state file with several records --- src/komodo_structs.cpp | 1 - src/komodo_structs.h | 8 +++++-- src/test-komodo/test_events.cpp | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 444a861eb37..bb4b8fb9106 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -2,7 +2,6 @@ extern std::mutex komodo_mutex; - /*** * komodo_state */ diff --git a/src/komodo_structs.h b/src/komodo_structs.h index da38fc7d3c4..9deef078a0a 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -91,12 +91,18 @@ enum komodo_event_type EVENT_PRICEFEED }; +/*** + * Thrown by event constructors when it finds a problem with the input data + */ class parse_error : public std::logic_error { public: parse_error(const std::string& in) : std::logic_error(in) {} }; +/*** + * base class for events + */ class event { public: @@ -107,7 +113,6 @@ class event }; std::ostream& operator<<(std::ostream& os, const event& in); - struct event_notarized : public event { event_notarized() : event(komodo_event_type::EVENT_NOTARIZED, 0), notarizedheight(0), MoMdepth(0) {} @@ -236,7 +241,6 @@ struct komodo_state std::list> events; uint32_t RTbufs[64][3]; uint64_t RTmask; bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); - }; #endif /* KOMODO_STRUCTS_H */ diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index 1a9d6987d90..98cbfe1ee19 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -459,6 +459,45 @@ TEST(TestEvents, komodo_faststateinit_test) komodo_event* ev1 = state->Komodo_events[7]; ASSERT_EQ(ev1->height, 1); ASSERT_EQ(ev1->type, 'P'); + // check that the new way is the same + ASSERT_EQ(state->events.size(), 14); + auto itr = state->events.begin(); + std::advance(itr, 7); + { + ASSERT_EQ( (*itr)->height, 1); + ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PUBKEYS); + itr++; + } + { + ASSERT_EQ( (*itr)->height, 1); + ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + itr++; + } + { + ASSERT_EQ( (*itr)->height, 1); + ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + itr++; + } + { + ASSERT_EQ( (*itr)->height, 1); + ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + itr++; + } + { + ASSERT_EQ( (*itr)->height, 1); + ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + itr++; + } + { + ASSERT_EQ( (*itr)->height, 1); + ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_OPRETURN); + itr++; + } + { + ASSERT_EQ( (*itr)->height, 1); + ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PRICEFEED); + itr++; + } } } catch(...) From 0f575cc9824bf7930f165078302058a83834f0a4 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 10 May 2021 11:08:53 -0500 Subject: [PATCH 06/58] forgot required #include --- src/komodo_globals.h | 1 + src/komodo_structs.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 98bd369a53a..e4445947a24 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -13,6 +13,7 @@ * * ******************************************************************************/ #pragma once +#include #include "komodo_defs.h" void komodo_prefetch(FILE *fp); diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index bb4b8fb9106..430644781aa 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -1,4 +1,5 @@ #include +#include extern std::mutex komodo_mutex; From fa5f91859c86771661699596f21c984ccc42eb17 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 18 May 2021 09:58:48 -0500 Subject: [PATCH 07/58] removed old way of deserializing event records --- src/komodo.h | 114 --------------------------------------------------- 1 file changed, 114 deletions(-) diff --git a/src/komodo.h b/src/komodo.h index c25b17bd4cc..f88886630a3 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -265,26 +265,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long errs++; if ( rec_type == 'P' ) // pubkey record { - // while we're doing both old and new way - long temp_pos = fpos; - // old way - int32_t num; - if ( (num = filedata[fpos++]) <= 64 ) // number of keys in this record - { - uint8_t pubkeys[64][33]; - if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) - errs++; - else - { - //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); - } - } - else - printf("illegal number of keys.%d\n",num); - fpos = temp_pos; - // new way try { std::shared_ptr pubkey = std::make_shared(filedata, fpos, datalen, ht); @@ -299,36 +279,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'N' || rec_type == 'M' ) // notary event { - // old way - long temp_pos = fpos; - int32_t notarized_height; - if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) - errs++; - uint256 notarized_hash; - if ( memread(¬arized_hash,sizeof(notarized_hash),filedata,&fpos,datalen) != sizeof(notarized_hash) ) - errs++; - uint256 notarized_desttxid; - if ( memread(¬arized_desttxid,sizeof(notarized_desttxid),filedata,&fpos,datalen) != sizeof(notarized_desttxid) ) - errs++; - int32_t MoMdepth; - uint256 MoM; - if ( rec_type == 'M' ) - { - if ( memread(&MoM,sizeof(MoM),filedata,&fpos,datalen) != sizeof(MoM) ) - errs++; - if ( memread(&MoMdepth,sizeof(MoMdepth),filedata,&fpos,datalen) != sizeof(MoMdepth) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); - } - else - { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - } - komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); - fpos = temp_pos; // reset for new way - // new way try { std::shared_ptr notarized = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'M'); @@ -353,14 +303,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'K' ) // kmd event { - long temp_pos = fpos; - // old way - int32_t kheight; - if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) - errs++; - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); - fpos = temp_pos; // reset for new way - // new way try { std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht); @@ -374,18 +316,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'T' ) // kmd event with timestamp { - long temp_pos = fpos; - // old way - int32_t kheight,ktimestamp; - if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) - errs++; - if ( memread(&ktimestamp,sizeof(ktimestamp),filedata,&fpos,datalen) != sizeof(ktimestamp) ) - errs++; - //if ( symbol_matches != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); - fpos = temp_pos; - // new way try { std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'T'); @@ -399,37 +329,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'R' ) // opreturn { - long temp_pos = fpos; - // old way - uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; - if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) - errs++; - if ( memread(&v,sizeof(v),filedata,&fpos,datalen) != sizeof(v) ) - errs++; - if ( memread(&ovalue,sizeof(ovalue),filedata,&fpos,datalen) != sizeof(ovalue) ) - errs++; - if ( memread(&olen,sizeof(olen),filedata,&fpos,datalen) != sizeof(olen) ) - errs++; - if ( olen < sizeof(opret) ) - { - if ( memread(opret,olen,filedata,&fpos,datalen) != olen ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && symbol_matches ) - { - int32_t i; for (i=0; i global PAX - } else - { - int32_t i; - for (i=0; i opret = std::make_shared(filedata, fpos, datalen, ht); @@ -447,19 +346,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( rec_type == 'V' ) // pricefeed { - long temp_pos = fpos; - // old way - int32_t numpvals; uint32_t pvals[128]; - numpvals = filedata[fpos++]; - if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && memread(pvals,(int32_t)(sizeof(uint32_t)*numpvals),filedata,&fpos,datalen) == numpvals*sizeof(uint32_t) ) - { - //if ( symbol_matches != 0 ) global shared state -> global PVALS - //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); - komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); - //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); - } else printf("error loading pvals[%d]\n",numpvals); - fpos = temp_pos; - // new way try { std::shared_ptr feed = std::make_shared(filedata, fpos, datalen, ht); From 77b11abed0c0426bc46801916a70eb5dbb911e10 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 18 May 2021 13:52:37 -0500 Subject: [PATCH 08/58] Initial split of h and cpp, paused at komodo_gateway.h --- src/Makefile.am | 32 +- src/bitcoind.cpp | 1 - src/cJSON.c | 4 +- src/cc/CCMarmara.h | 47 - src/cc/CCinclude.h | 9 +- src/cc/Makefile | 25 +- src/cc/crypto777/OS_portable.h | 3 - src/cc/marmara.cpp | 1104 ---------- src/cc/rogue/extern.h | 2 - src/cryptoconditions/src/threshold.c | 2 +- src/cryptoconditions/src/utils.c | 4 +- src/komodo.cpp | 1199 ++++++++++ src/komodo.h | 1058 +-------- src/komodo_bitcoind.cpp | 2842 ++++++++++++++++++++++++ src/komodo_bitcoind.h | 3032 ++------------------------ src/komodo_cJSON.c | 4 - src/komodo_cJSON.h | 19 +- src/komodo_ccdata.cpp | 267 +++ src/komodo_ccdata.h | 255 +-- src/komodo_curve25519.cpp | 267 +++ src/komodo_curve25519.h | 264 +-- src/komodo_events.cpp | 222 ++ src/komodo_events.h | 232 +- src/komodo_gateway.cpp | 2774 +++++++++++++++++++++++ src/komodo_gateway.h | 2923 ++----------------------- 25 files changed, 8142 insertions(+), 8449 deletions(-) delete mode 100644 src/cc/CCMarmara.h delete mode 100644 src/cc/marmara.cpp create mode 100644 src/komodo.cpp create mode 100644 src/komodo_bitcoind.cpp create mode 100644 src/komodo_ccdata.cpp create mode 100644 src/komodo_curve25519.cpp create mode 100644 src/komodo_events.cpp create mode 100644 src/komodo_gateway.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 28304d11598..cb8ee654d5a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,13 +32,13 @@ BITCOIN_INCLUDES += -I$(srcdir)/snark/libsnark BITCOIN_INCLUDES += -I$(srcdir)/univalue/include if TARGET_WINDOWS -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl +LIBBITCOIN_SERVER=libbitcoin_server.a endif if TARGET_DARWIN -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl +LIBBITCOIN_SERVER=libbitcoin_server.a endif if TARGET_LINUX -LIBBITCOIN_SERVER=libbitcoin_server.a -lcurl +LIBBITCOIN_SERVER=libbitcoin_server.a endif LIBBITCOIN_WALLET=libbitcoin_wallet.a @@ -53,6 +53,7 @@ LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a +LIBCJSON-libcjson.a if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a @@ -91,6 +92,12 @@ $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " +%.o: %.c + $(CC) -c -o $@ $< + +$(LIBCJSON): cJSON.o komodo_cJSON.o komodo_cutils.o + $(AR) cr $(LIBCJSON) $^ + # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ @@ -306,7 +313,6 @@ libbitcoin_server_a_SOURCES = \ cc/oracles.cpp \ cc/prices.cpp \ cc/pegs.cpp \ - cc/marmara.cpp \ cc/payments.cpp \ cc/gateways.cpp \ cc/channels.cpp \ @@ -353,6 +359,7 @@ libbitcoin_server_a_SOURCES = \ txdb.cpp \ txmempool.cpp \ validationinterface.cpp \ + mini-gmp.c \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -483,6 +490,19 @@ libbitcoin_common_a_SOURCES = \ key_io.cpp \ keystore.cpp \ komodo_structs.cpp \ + komodo.cpp \ + komodo_bitcoind.cpp \ + komodo_ccdata.cpp \ + komodo_curve25519.cpp \ + komodo_events.cpp \ + komodo_gateway.cpp \ + komodo_globals.cpp \ + komodo_interest.cpp \ + komodo_jumblr.cpp \ + komodo_kv.cpp \ + komodo_notary.cpp \ + komodo_pax.cpp \ + komodo_utils.cpp \ netbase.cpp \ metrics.cpp \ primitives/block.cpp \ @@ -581,6 +601,7 @@ komodod_LDADD += $(LIBBITCOIN_WALLET) endif komodod_LDADD += \ + $(LIBCJSON) \ $(BOOST_LIBS) \ $(BDB_LIBS) \ $(SSL_LIBS) \ @@ -592,7 +613,8 @@ komodod_LDADD += \ $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH_LIBS) + $(LIBZCASH_LIBS) \ + -lcurl if TARGET_DARWIN komodod_LDADD += libcc.dylib $(LIBSECP256K1) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index ef7b09a37f0..d249b7934d5 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -57,7 +57,6 @@ static bool fDaemon; #include "komodo_defs.h" -#define KOMODO_ASSETCHAIN_MAXLEN 65 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern int32_t ASSETCHAINS_BLOCKTIME; extern uint64_t ASSETCHAINS_CBOPRET; diff --git a/src/cJSON.c b/src/cJSON.c index 09da0688983..bbead0587d7 100644 --- a/src/cJSON.c +++ b/src/cJSON.c @@ -58,8 +58,8 @@ #include "cJSON.h" /* define our own boolean type */ -//#define true ((cJSON_bool)1) -//#define false ((cJSON_bool)0) +#define true ((cJSON_bool)1) +#define false ((cJSON_bool)0) typedef struct { const unsigned char *json; diff --git a/src/cc/CCMarmara.h b/src/cc/CCMarmara.h deleted file mode 100644 index 85f9175d17a..00000000000 --- a/src/cc/CCMarmara.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * 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. * - * * - ******************************************************************************/ - - -#ifndef CC_MARMARA_H -#define CC_MARMARA_H - -#include "CCinclude.h" -#include "../komodo_cJSON.h" - -#define MARMARA_GROUPSIZE 60 -#define MARMARA_MINLOCK (1440 * 3 * 30) -#define MARMARA_MAXLOCK (1440 * 24 * 30) -#define MARMARA_VINS 16 -#define EVAL_MARMARA 0xef - -extern uint8_t ASSETCHAINS_MARMARA; -uint64_t komodo_block_prg(uint32_t nHeight); -int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid); -int32_t MarmaraGetbatontxid(std::vector &creditloop,uint256 &batontxid,uint256 txid); -UniValue MarmaraCreditloop(uint256 txid); -UniValue MarmaraSettlement(uint64_t txfee,uint256 batontxid); -UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height); - -UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr); // [[pk0, shares0], [pk1, shares1], ...] -UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag); -UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid); -UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency); - -bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); - -// CCcustom -UniValue MarmaraInfo(); - -#endif diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 1d28e2cc939..653ab8f4a0e 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -16,6 +16,8 @@ #ifndef CC_INCLUDE_H #define CC_INCLUDE_H +#include "komodo_cutils.h" // for decode_hex and is_hexstr + /*! \file CCinclude.h \brief A Documented file. @@ -285,13 +287,6 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo /// @param[out] currentheight current chain height bool NSPV_myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, int32_t &txheight, int32_t ¤theight); -/// decodes char array in hex encoding to byte array -int32_t decode_hex(uint8_t *bytes, int32_t n, char *hex); - -/// checks if char string has hex symbols -/// @returns no zero if string has only hex symbols -int32_t is_hexstr(char *str,int32_t n); - /// CCgettxout returns the amount of an utxo. The function does this without loading the utxo transaction from the chain, by using coin cache /// @param txid transaction id of the utxo /// @param vout utxo transaction vout order number diff --git a/src/cc/Makefile b/src/cc/Makefile index 3e988f27935..24b94226a5a 100644 --- a/src/cc/Makefile +++ b/src/cc/Makefile @@ -2,9 +2,10 @@ SHELL = /bin/sh CC = gcc CC_DARWIN = g++-6 CC_WIN = x86_64-w64-mingw32-gcc-posix -CFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib -CFLAGS = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -CFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c +CFLAGS = -arch x86_64 +CXXFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib +CXXFLAGS = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c +CXXFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c DEBUGFLAGS = -O0 -D _DEBUG RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) @@ -13,21 +14,27 @@ $(info $(OS)) TARGET = ../libcc.so TARGET_DARWIN = ../libcc.dylib TARGET_WIN = ../libcc.dll -SOURCES = cclib.cpp -#HEADERS = $(shell echo ../cryptoconditions/include/*.h) +SOURCES = cclib.cpp ../cJSON.c +OBJS = cclib.o ../cJSON.o all: $(TARGET) -$(TARGET): $(SOURCES) +%.o: %.c + $(CC) -o $@ $< $(CFLAGS) $(DEBUGFLAGS) + +%.o: %.cpp + $(CC) -o $@ $< $(CXXFLAGS) $(DEBUGFLAGS) + +$(TARGET): $(OBJS) $(info Building cclib to src/) ifeq ($(OS),Darwin) - $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(SOURCES) + $(CC_DARWIN) $(CXXFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(OBJS) else ifeq ($(OS),Linux) - $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(SOURCES) + $(CC) $(CXXFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJS) #else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host else $(info WINDOWS) - $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(SOURCES) + $(CC_WIN) $(CXXFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(OBJS) endif clean: diff --git a/src/cc/crypto777/OS_portable.h b/src/cc/crypto777/OS_portable.h index e0b185cbc72..235ffccf4d2 100755 --- a/src/cc/crypto777/OS_portable.h +++ b/src/cc/crypto777/OS_portable.h @@ -297,9 +297,6 @@ int32_t unstringbits(char *buf,uint64_t bits); uint64_t stringbits(char *str); int32_t is_decimalstr(char *str); void tolowercase(char *str); -char *clonestr(char *str); -int32_t is_hexstr(char *str,int32_t n); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); void reverse_hexstr(char *str); int32_t init_hexbytes_noT(char *hexbytes,uint8_t *message,long len); uint16_t parse_ipaddr(char *ipaddr,char *ip_port); diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp deleted file mode 100644 index 68625c0382b..00000000000 --- a/src/cc/marmara.cpp +++ /dev/null @@ -1,1104 +0,0 @@ -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * 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. * - * * - ******************************************************************************/ - -#include "CCMarmara.h" - -/* - Marmara CC is for the MARMARA project - - 'R': two forms for initial issuance and for accepting existing - vins normal - vout0 approval to senderpk (issuer or owner of baton) - - 'I' - vin0 approval from 'R' - vins1+ normal - vout0 baton to 1st receiverpk - vout1 marker to Marmara so all issuances can be tracked (spent when loop is closed) - - 'T' - vin0 approval from 'R' - vin1 baton from 'I'/'T' - vins2+ normal - vout0 baton to next receiverpk (following the unspent baton back to original is the credit loop) - - 'S' - vin0 'I' marker - vin1 baton - vins CC utxos from credit loop - - 'D' default/partial payment - - 'L' lockfunds - -*/ - -// start of consensus code - -int64_t IsMarmaravout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v) -{ - char destaddr[64]; - if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) - { - if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) - return(tx.vout[v].nValue); - } - return(0); -} - -int32_t MarmaraRandomize(uint32_t ind) -{ - uint64_t val64; uint32_t val,range = (MARMARA_MAXLOCK - MARMARA_MINLOCK); - val64 = komodo_block_prg(ind); - val = (uint32_t)(val64 >> 32); - val ^= (uint32_t)val64; - return((val % range) + MARMARA_MINLOCK); -} - -int32_t MarmaraUnlockht(int32_t height) -{ - uint32_t ind = height / MARMARA_GROUPSIZE; - height = (height / MARMARA_GROUPSIZE) * MARMARA_GROUPSIZE; - return(height + MarmaraRandomize(ind)); -} - -uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht) -{ - std::vector vopret; uint8_t *script,e,f,funcid; - GetOpReturnData(scriptPubKey,vopret); - script = (uint8_t *)vopret.data(); - if ( 0 ) - { - int32_t i; - for (i=0; i 2 && script[0] == EVAL_MARMARA ) - { - if ( script[1] == 'C' || script[1] == 'P' || script[1] == 'L' ) - { - if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> height; ss >> unlockht) != 0 ) - { - return(script[1]); - } else fprintf(stderr,"DecodeMaramaraCoinbaseOpRet unmarshal error for %c\n",script[1]); - } //else fprintf(stderr,"script[1] is %d != 'C' %d or 'P' %d or 'L' %d\n",script[1],'C','P','L'); - } else fprintf(stderr,"vopret.size() is %d\n",(int32_t)vopret.size()); - return(0); -} - -CScript EncodeMarmaraCoinbaseOpRet(uint8_t funcid,CPubKey pk,int32_t ht) -{ - CScript opret; int32_t unlockht; uint8_t evalcode = EVAL_MARMARA; - unlockht = MarmaraUnlockht(ht); - opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk << ht << unlockht); - if ( 0 ) - { - std::vector vopret; uint8_t *script,i; - GetOpReturnData(opret,vopret); - script = (uint8_t *)vopret.data(); - { - for (i=0; i vopret; uint8_t *script,e,f; - GetOpReturnData(scriptPubKey, vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> createtxid; ss >> senderpk; ss >> amount; ss >> matures; ss >> currency) != 0 ) - { - return(f); - } - return(0); -} - -int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid) -{ - CTransaction tx; uint256 hashBlock; uint8_t funcid; int32_t numvouts,matures; std::string currency; CPubKey senderpk; int64_t amount; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,senderpk,amount,matures,currency)) == 'I' || funcid == 'T' ) - return(0); - else if ( funcid == 'R' ) - { - if ( createtxid == zeroid ) - createtxid = txid; - return(0); - } - } - return(-1); -} - -int32_t MarmaraGetbatontxid(std::vector &creditloop,uint256 &batontxid,uint256 txid) -{ - uint256 createtxid,spenttxid; int64_t value; int32_t vini,height,n=0,vout = 0; - memset(&batontxid,0,sizeof(batontxid)); - if ( MarmaraGetcreatetxid(createtxid,txid) == 0 ) - { - txid = createtxid; - //fprintf(stderr,"txid.%s -> createtxid %s\n",txid.GetHex().c_str(),createtxid.GetHex().c_str()); - while ( CCgetspenttxid(spenttxid,vini,height,txid,vout) == 0 ) - { - creditloop.push_back(txid); - //fprintf(stderr,"%d: %s\n",n,txid.GetHex().c_str()); - n++; - if ( (value= CCgettxout(spenttxid,vout,1,1)) == 10000 ) - { - batontxid = spenttxid; - //fprintf(stderr,"got baton %s %.8f\n",batontxid.GetHex().c_str(),(double)value/COIN); - return(n); - } - else if ( value > 0 ) - { - batontxid = spenttxid; - fprintf(stderr,"n.%d got false baton %s/v%d %.8f\n",n,batontxid.GetHex().c_str(),vout,(double)value/COIN); - return(n); - } - // get funcid - txid = spenttxid; - } - } - return(-1); -} - -CScript Marmara_scriptPubKey(int32_t height,CPubKey pk) -{ - CTxOut ccvout; struct CCcontract_info *cp,C; CPubKey Marmarapk; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) - { - ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk); - //char coinaddr[64]; - //Getscriptaddress(coinaddr,ccvout.scriptPubKey); - //fprintf(stderr,"Marmara_scriptPubKey %s ht.%d -> %s\n",HexStr(pk).c_str(),height,coinaddr); - } - return(ccvout.scriptPubKey); -} - -CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk) -{ - uint8_t *ptr; - //fprintf(stderr,"height.%d pksize.%d\n",height,(int32_t)pk.size()); - if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) - return(EncodeMarmaraCoinbaseOpRet(funcid,pk,height)); - return(CScript()); -} - -int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx) -{ - struct CCcontract_info *cp,C; CPubKey Marmarapk,pk; int32_t ht,unlockht; CTxOut ccvout; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - if ( 0 ) - { - int32_t d,histo[365*2+30]; - memset(histo,0,sizeof(histo)); - for (ht=2; ht<100; ht++) - fprintf(stderr,"%d ",MarmaraUnlockht(ht)); - fprintf(stderr," <- first 100 unlock heights\n"); - for (ht=2; ht<1000000; ht+=MARMARA_GROUPSIZE) - { - d = (MarmaraUnlockht(ht) - ht) / 1440; - if ( d < 0 || d > sizeof(histo)/sizeof(*histo) ) - fprintf(stderr,"d error.%d at ht.%d\n",d,ht); - else histo[d]++; - } - for (ht=0; ht unlock.%d\n",ht,unlockht); - ccvout = MakeCC1of2vout(EVAL_MARMARA,0,Marmarapk,pk); - if ( ccvout.scriptPubKey == tx.vout[0].scriptPubKey ) - return(0); - char addr0[64],addr1[64]; - Getscriptaddress(addr0,ccvout.scriptPubKey); - Getscriptaddress(addr1,tx.vout[0].scriptPubKey); - fprintf(stderr,"ht.%d mismatched CCvout scriptPubKey %s vs %s pk.%d %s\n",height,addr0,addr1,(int32_t)pk.size(),HexStr(pk).c_str()); - } else fprintf(stderr,"ht.%d %d vs %d unlock.%d\n",height,MarmaraUnlockht(height),ht,unlockht); - } else fprintf(stderr,"ht.%d error decoding coinbase opret\n",height); - } - return(-1); -} - -bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx) -{ - CPubKey Marmarapk,pk; int32_t height,unlockht; uint8_t funcid; char coinaddr[64]; struct CCcontract_info *cp,C; - //fprintf(stderr,"%s numvins.%d numvouts.%d %.8f opret[%d]\n",staketx.GetHash().ToString().c_str(),(int32_t)staketx.vin.size(),(int32_t)staketx.vout.size(),(double)staketx.vout[0].nValue/COIN,(int32_t)opret.size()); - if ( staketx.vout.size() == 2 && opret == staketx.vout[1].scriptPubKey ) - { - cp = CCinit(&C,EVAL_MARMARA); - funcid = DecodeMaramaraCoinbaseOpRet(opret,pk,height,unlockht); - Marmarapk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); - //fprintf(stderr,"matched opret! funcid.%c ht.%d unlock.%d %s\n",funcid,height,unlockht,coinaddr); - return(strcmp(destaddr,coinaddr) == 0); - } - return(0); -} - -bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) -{ - std::vector vopret; CTransaction vinTx; uint256 hashBlock; int32_t numvins,numvouts,i,ht,unlockht,vht,vunlockht; uint8_t funcid,vfuncid,*script; CPubKey pk,vpk; - if ( ASSETCHAINS_MARMARA == 0 ) - return eval->Invalid("-ac_marmara must be set for marmara CC"); - numvins = tx.vin.size(); - numvouts = tx.vout.size(); - if ( numvouts < 1 ) - return eval->Invalid("no vouts"); - else if ( tx.vout.size() >= 2 ) - { - GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey,vopret); - script = (uint8_t *)vopret.data(); - if ( vopret.size() < 2 || script[0] != EVAL_MARMARA ) - return eval->Invalid("no opreturn"); - funcid = script[1]; - if ( funcid == 'P' ) - { - funcid = DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht); - for (i=0; iismyvin)(tx.vin[i].scriptSig) != 0 ) - { - if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) - return eval->Invalid("cant find vinTx"); - else - { - if ( vinTx.IsCoinBase() == 0 ) - return eval->Invalid("noncoinbase input"); - else if ( vinTx.vout.size() != 2 ) - return eval->Invalid("coinbase doesnt have 2 vouts"); - vfuncid = DecodeMaramaraCoinbaseOpRet(vinTx.vout[1].scriptPubKey,vpk,vht,vunlockht); - if ( vfuncid != 'C' || vpk != pk || vunlockht != unlockht ) - return eval->Invalid("mismatched opreturn"); - } - } - } - return(true); - } - else if ( funcid == 'L' ) // lock -> lock funds with a unlockht - { - return(true); - } - else if ( funcid == 'R' ) // receive -> agree to receive 'I' from pk, amount, currency, dueht - { - return(true); - } - else if ( funcid == 'I' ) // issue -> issue currency to pk with due date height - { - return(true); - } - else if ( funcid == 'T' ) // transfer -> given 'R' transfer 'I' or 'T' to the pk of 'R' - { - return(true); - } - else if ( funcid == 'S' ) // settlement -> automatically spend issuers locked funds, given 'I' - { - return(true); - } - else if ( funcid == 'D' ) // insufficient settlement - { - return(true); - } - else if ( funcid == 'C' ) // coinbase - { - return(true); - } - // staking only for locked utxo - } - return eval->Invalid("fall through error"); -} -// end of consensus code - -// helper functions for rpc calls in rpcwallet.cpp - -int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx,int32_t firstheight,CPubKey poolpk,int32_t maxinputs) -{ - char coinaddr[64]; CPubKey Marmarapk,pk; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction vintx; int32_t unlockht,ht,vout,unlocks,n = 0; - std::vector > unspentOutputs; - Marmarapk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,Marmarapk,poolpk); - SetCCunspents(unspentOutputs,coinaddr,true); - unlocks = MarmaraUnlockht(firstheight); - //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - //fprintf(stderr,"txid.%s/v%d\n",txid.GetHex().c_str(),vout); - if ( myGetTransaction(txid,vintx,hashBlock) != 0 ) - { - if ( vintx.IsCoinBase() != 0 && vintx.vout.size() == 2 && vintx.vout[1].nValue == 0 ) - { - if ( DecodeMaramaraCoinbaseOpRet(vintx.vout[1].scriptPubKey,pk,ht,unlockht) == 'C' && unlockht == unlocks && pk == poolpk && ht >= firstheight ) - { - if ( (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( maxinputs > 0 && n >= maxinputs ) - break; - } //else fprintf(stderr,"nValue.%8f\n",(double)nValue/COIN); - } //else fprintf(stderr,"decode error unlockht.%d vs %d pk.%d\n",unlockht,unlocks,pk == poolpk); - } else fprintf(stderr,"not coinbase\n"); - } else fprintf(stderr,"error getting tx\n"); - } - return(totalinputs); -} - -int64_t AddMarmarainputs(CMutableTransaction &mtx,std::vector &pubkeys,char *coinaddr,int64_t total,int32_t maxinputs) -{ - uint64_t threshold,nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction tx; int32_t numvouts,ht,unlockht,vout,i,n = 0; uint8_t funcid; CPubKey pk; std::vector vals; - std::vector > unspentOutputs; - SetCCunspents(unspentOutputs,coinaddr,true); - if ( maxinputs > CC_MAXVINS ) - maxinputs = CC_MAXVINS; - if ( maxinputs > 0 ) - threshold = total/maxinputs; - else threshold = total; - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - if ( it->second.satoshis < threshold ) - continue; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' ) - { - //char str[64]; fprintf(stderr,"(%s) %s/v%d %.8f ht.%d unlockht.%d\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN,ht,unlockht); - if ( total != 0 && maxinputs != 0 ) - { - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - pubkeys.push_back(pk); - } - totalinputs += it->second.satoshis; - vals.push_back(it->second.satoshis); - n++; - if ( maxinputs != 0 && total == 0 ) - continue; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; - } else fprintf(stderr,"null funcid\n"); - } - } - if ( maxinputs != 0 && total == 0 ) - { - std::sort(vals.begin(),vals.end()); - totalinputs = 0; - for (i=0; i txfee ) - inputsum = AddNormalinputs2(mtx,val,CC_MAXVINS/2); - //fprintf(stderr,"normal inputs %.8f val %.8f\n",(double)inputsum/COIN,(double)val/COIN); - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,amount,Marmarapk,mypk)); - if ( inputsum < amount+txfee ) - { - refunlockht = MarmaraUnlockht(height); - result.push_back(Pair("normalfunds",ValueFromAmount(inputsum))); - result.push_back(Pair("height",height)); - result.push_back(Pair("unlockht",refunlockht)); - remains = (amount + txfee) - inputsum; - std::vector > unspentOutputs; - GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk); - SetCCunspents(unspentOutputs,coinaddr,true); - threshold = remains / (MARMARA_VINS+1); - uint8_t mypriv[32]; - Myprivkey(mypriv); - CCaddr1of2set(cp,Marmarapk,mypk,mypriv,coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - if ( (nValue= it->second.satoshis) < threshold ) - continue; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 && vout < numvouts && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - if ( (funcid= DecodeMaramaraCoinbaseOpRet(tx.vout[numvouts-1].scriptPubKey,pk,ht,unlockht)) == 'C' || funcid == 'P' || funcid == 'L' ) - { - if ( unlockht < refunlockht ) - { - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - //fprintf(stderr,"merge CC vout %s/v%d %.8f unlockht.%d < ref.%d\n",txid.GetHex().c_str(),vout,(double)nValue/COIN,unlockht,refunlockht); - inputsum += nValue; - remains -= nValue; - if ( inputsum >= amount + txfee ) - { - //fprintf(stderr,"inputsum %.8f >= amount %.8f, update amount\n",(double)inputsum/COIN,(double)amount/COIN); - amount = inputsum - txfee; - break; - } - } - } - } - } - memset(mypriv,0,sizeof(mypriv)); - } - if ( inputsum >= amount+txfee ) - { - if ( inputsum > amount+txfee ) - { - change = (inputsum - amount); - mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - } - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraCoinbaseOpret('L',height,mypk)); - if ( rawtx.size() == 0 ) - errorstr = (char *)"couldnt finalize CCtx"; - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - return(result); - } - } else errorstr = (char *)"insufficient funds"; - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",errorstr)); - return(result); -} - -int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &mtx) -{ - uint256 txid,hashBlock; uint8_t *ptr; int32_t i,siglen,vout,numvouts; CTransaction tx; std::string rawtx; CPubKey mypk; std::vector pubkeys; struct CCcontract_info *cp,C; uint64_t txfee; - txfee = 10000; - vout = mtx.vin[0].prevout.n; - if ( myGetTransaction(mtx.vin[0].prevout.hash,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 && vout < numvouts ) - { - cp = CCinit(&C,EVAL_MARMARA); - mypk = pubkey2pk(Mypubkey()); - pubkeys.push_back(mypk); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,tx.vout[numvouts - 1].scriptPubKey,pubkeys); - if ( rawtx.size() > 0 ) - { - siglen = mtx.vin[0].scriptSig.size(); - ptr = &mtx.vin[0].scriptSig[0]; - for (i=0; i from utxo making change - -UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures,height; int64_t amount,refamount,remaining,inputsum,change; CPubKey Marmarapk,mypk,pk; std::string currency,refcurrency,rawtx; CTransaction tx,batontx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2],txidaddr[64]; std::vector pubkeys; struct CCcontract_info *cp,C; - if ( txfee == 0 ) - txfee = 10000; - cp = CCinit(&C,EVAL_MARMARA); - mypk = pubkey2pk(Mypubkey()); - Marmarapk = GetUnspendable(cp,0); - remaining = change = 0; - height = chainActive.LastTip()->GetHeight(); - if ( (n= MarmaraGetbatontxid(creditloop,batontxid,refbatontxid)) > 0 ) - { - if ( myGetTransaction(batontxid,batontx,hashBlock) != 0 && (numvouts= batontx.vout.size()) > 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(batontx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) - { - if ( refcreatetxid != creditloop[0] ) - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"invalid refcreatetxid, setting to creditloop[0]")); - return(result); - } - else if ( chainActive.LastTip()->GetHeight() < refmatures ) - { - fprintf(stderr,"doesnt mature for another %d blocks\n",refmatures - chainActive.LastTip()->GetHeight()); - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"cant settle immature creditloop")); - return(result); - } - else if ( (refmatures & 1) == 0 ) - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"cant automatic settle even maturity heights")); - return(result); - } - else if ( n < 1 ) - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"creditloop too short")); - return(result); - } - remaining = refamount; - GetCCaddress(cp,myCCaddr,Mypubkey()); - Getscriptaddress(batonCCaddr,batontx.vout[0].scriptPubKey); - if ( strcmp(myCCaddr,batonCCaddr) == 0 ) - { - mtx.vin.push_back(CTxIn(n == 1 ? batontxid : creditloop[1],1,CScript())); // issuance marker - pubkeys.push_back(Marmarapk); - mtx.vin.push_back(CTxIn(batontxid,0,CScript())); - pubkeys.push_back(mypk); - for (i=1; i 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) - { - GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); - if ( (inputsum= AddMarmarainputs(mtx,pubkeys,coinaddr,remaining,MARMARA_VINS)) >= remaining ) - { - change = (inputsum - remaining); - mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - if ( change > txfee ) - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,change,Marmarapk,pk)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('S',createtxid,mypk,0,refmatures,currency),pubkeys); - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - return(result); - } else remaining -= inputsum; - if ( mtx.vin.size() >= CC_MAXVINS - MARMARA_VINS ) - break; - } else fprintf(stderr,"null funcid for creditloop[%d]\n",i); - } else fprintf(stderr,"couldnt get creditloop[%d]\n",i); - } - if ( refamount - remaining > 2*txfee ) - { - mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,createtxid))) << OP_CHECKSIG)); // failure marker - if ( refamount-remaining > 3*txfee ) - mtx.vout.push_back(CTxOut(refamount-remaining-2*txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('D',createtxid,mypk,-remaining,refmatures,currency),pubkeys); - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"insufficient funds")); - result.push_back(Pair("hex",rawtx)); - result.push_back(Pair("remaining",ValueFromAmount(remaining))); - } - else - { - // jl777: maybe fund a txfee to report no funds avail - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"no funds available at all")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"this node does not have the baton")); - result.push_back(Pair("myCCaddr",myCCaddr)); - result.push_back(Pair("batonCCaddr",batonCCaddr)); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt find batontxid")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get creditloop")); - } - return(result); -} - -int32_t MarmaraGetCreditloops(int64_t &totalamount,std::vector &issuances,int64_t &totalclosed,std::vector &closed,struct CCcontract_info *cp,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,CPubKey refpk,std::string refcurrency) -{ - char coinaddr[64]; CPubKey Marmarapk,senderpk; int64_t amount; uint256 createtxid,txid,hashBlock; CTransaction tx; int32_t numvouts,vout,matures,n=0; std::string currency; - std::vector > unspentOutputs; - Marmarapk = GetUnspendable(cp,0); - GetCCaddress(cp,coinaddr,Marmarapk); - SetCCunspents(unspentOutputs,coinaddr,true); - // do all txid, conditional on spent/unspent - //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - //fprintf(stderr,"txid.%s/v%d\n",txid.GetHex().c_str(),vout); - if ( vout == 1 && myGetTransaction(txid,tx,hashBlock) != 0 ) - { - if ( tx.IsCoinBase() == 0 && (numvouts= tx.vout.size()) > 2 && tx.vout[numvouts - 1].nValue == 0 ) - { - if ( MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,senderpk,amount,matures,currency) == 'I' ) - { - n++; - if ( currency == refcurrency && matures >= firstheight && matures <= lastheight && amount >= minamount && amount <= maxamount && (refpk.size() == 0 || senderpk == refpk) ) - { - issuances.push_back(txid); - totalamount += amount; - } - } - } - } else fprintf(stderr,"error getting tx\n"); - } - return(n); -} - -UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 batontxid,bool automaticflag) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ); CPubKey mypk; struct CCcontract_info *cp,C; std::string rawtx; char *errorstr=0; uint256 createtxid; int64_t batonamount; int32_t needbaton = 0; - cp = CCinit(&C,EVAL_MARMARA); - if ( txfee == 0 ) - txfee = 10000; - if ( automaticflag != 0 && (matures & 1) == 0 ) - matures++; - else if ( automaticflag == 0 && (matures & 1) != 0 ) - matures++; - mypk = pubkey2pk(Mypubkey()); - memset(&createtxid,0,sizeof(createtxid)); - if ( batontxid != zeroid && MarmaraGetcreatetxid(createtxid,batontxid) < 0 ) - errorstr = (char *)"cant get createtxid from batontxid"; - else if ( currency != "MARMARA" ) - errorstr = (char *)"for now, only MARMARA loops are supported"; - else if ( amount <= txfee ) - errorstr = (char *)"amount must be for more than txfee"; - else if ( matures <= chainActive.LastTip()->GetHeight() ) - errorstr = (char *)"it must mature in the future"; - if ( errorstr == 0 ) - { - if ( batontxid != zeroid ) - batonamount = txfee; - else batonamount = 2*txfee; - if ( AddNormalinputs(mtx,mypk,batonamount + txfee,1) > 0 ) - { - errorstr = (char *)"couldnt finalize CCtx"; - mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,batonamount,senderpk)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('R',createtxid,senderpk,amount,matures,currency)); - if ( rawtx.size() > 0 ) - errorstr = 0; - } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; - } - if ( rawtx.size() == 0 || errorstr != 0 ) - { - result.push_back(Pair("result","error")); - if ( errorstr != 0 ) - result.push_back(Pair("error",errorstr)); - } - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - result.push_back(Pair("funcid","R")); - result.push_back(Pair("createtxid",createtxid.GetHex())); - if ( batontxid != zeroid ) - result.push_back(Pair("batontxid",batontxid.GetHex())); - result.push_back(Pair("senderpk",HexStr(senderpk))); - result.push_back(Pair("amount",ValueFromAmount(amount))); - result.push_back(Pair("matures",matures)); - result.push_back(Pair("currency",currency)); - } - return(result); -} - -UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 approvaltxid,uint256 batontxid) -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ); CPubKey mypk,Marmarapk; struct CCcontract_info *cp,C; std::string rawtx; uint256 createtxid; char *errorstr=0; - cp = CCinit(&C,EVAL_MARMARA); - if ( txfee == 0 ) - txfee = 10000; - // make sure less than maxlength - Marmarapk = GetUnspendable(cp,0); - mypk = pubkey2pk(Mypubkey()); - if ( MarmaraGetcreatetxid(createtxid,approvaltxid) < 0 ) - errorstr = (char *)"cant get createtxid from approvaltxid"; - else if ( currency != "MARMARA" ) - errorstr = (char *)"for now, only MARMARA loops are supported"; - else if ( amount <= txfee ) - errorstr = (char *)"amount must be for more than txfee"; - else if ( matures <= chainActive.LastTip()->GetHeight() ) - errorstr = (char *)"it must mature in the future"; - if ( errorstr == 0 ) - { - mtx.vin.push_back(CTxIn(approvaltxid,0,CScript())); - if ( funcid == 'T' ) - mtx.vin.push_back(CTxIn(batontxid,0,CScript())); - if ( funcid == 'I' || AddNormalinputs(mtx,mypk,txfee,1) > 0 ) - { - errorstr = (char *)"couldnt finalize CCtx"; - mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,receiverpk)); - if ( funcid == 'I' ) - mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,Marmarapk)); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret(funcid,createtxid,receiverpk,amount,matures,currency)); - if ( rawtx.size() > 0 ) - errorstr = 0; - } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; - } - if ( rawtx.size() == 0 || errorstr != 0 ) - { - result.push_back(Pair("result","error")); - if ( errorstr != 0 ) - result.push_back(Pair("error",errorstr)); - } - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - char str[2]; str[0] = funcid, str[1] = 0; - result.push_back(Pair("funcid",str)); - result.push_back(Pair("createtxid",createtxid.GetHex())); - result.push_back(Pair("approvaltxid",approvaltxid.GetHex())); - if ( funcid == 'T' ) - result.push_back(Pair("batontxid",batontxid.GetHex())); - result.push_back(Pair("receiverpk",HexStr(receiverpk))); - result.push_back(Pair("amount",ValueFromAmount(amount))); - result.push_back(Pair("matures",matures)); - result.push_back(Pair("currency",currency)); - } - return(result); -} - -UniValue MarmaraCreditloop(uint256 txid) -{ - UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey pk; std::string currency,refcurrency; CTransaction tx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_MARMARA); - if ( (n= MarmaraGetbatontxid(creditloop,batontxid,txid)) > 0 ) - { - if ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 ) - { - result.push_back(Pair("result",(char *)"success")); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG); - result.push_back(Pair("myaddress",coinaddr)); - GetCCaddress(cp,myCCaddr,Mypubkey()); - result.push_back(Pair("myCCaddress",myCCaddr)); - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) - { - str[0] = funcid, str[1] = 0; - result.push_back(Pair("funcid",str)); - result.push_back(Pair("currency",refcurrency)); - if ( funcid == 'S' ) - { - refcreatetxid = creditloop[0]; - result.push_back(Pair("settlement",batontxid.GetHex())); - result.push_back(Pair("createtxid",refcreatetxid.GetHex())); - result.push_back(Pair("remainder",ValueFromAmount(refamount))); - result.push_back(Pair("settled",refmatures)); - result.push_back(Pair("pubkey",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - result.push_back(Pair("coinaddr",coinaddr)); - result.push_back(Pair("collected",ValueFromAmount(tx.vout[0].nValue))); - Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); - if ( strcmp(coinaddr,destaddr) != 0 ) - { - result.push_back(Pair("destaddr",destaddr)); - numerrs++; - } - refamount = -1; - } - else if ( funcid == 'D' ) - { - refcreatetxid = creditloop[0]; - result.push_back(Pair("settlement",batontxid.GetHex())); - result.push_back(Pair("createtxid",refcreatetxid.GetHex())); - result.push_back(Pair("remainder",ValueFromAmount(refamount))); - result.push_back(Pair("settled",refmatures)); - Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); - result.push_back(Pair("txidaddr",destaddr)); - if ( tx.vout.size() > 1 ) - result.push_back(Pair("collected",ValueFromAmount(tx.vout[1].nValue))); - } - else - { - result.push_back(Pair("batontxid",batontxid.GetHex())); - result.push_back(Pair("createtxid",refcreatetxid.GetHex())); - result.push_back(Pair("amount",ValueFromAmount(refamount))); - result.push_back(Pair("matures",refmatures)); - if ( refcreatetxid != creditloop[0] ) - { - fprintf(stderr,"invalid refcreatetxid, setting to creditloop[0]\n"); - refcreatetxid = creditloop[0]; - numerrs++; - } - result.push_back(Pair("batonpk",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - result.push_back(Pair("batonaddr",coinaddr)); - GetCCaddress(cp,batonCCaddr,pk); - result.push_back(Pair("batonCCaddr",batonCCaddr)); - Getscriptaddress(coinaddr,tx.vout[0].scriptPubKey); - if ( strcmp(coinaddr,batonCCaddr) != 0 ) - { - result.push_back(Pair("vout0address",coinaddr)); - numerrs++; - } - if ( strcmp(myCCaddr,coinaddr) == 0 ) - result.push_back(Pair("ismine",1)); - else result.push_back(Pair("ismine",0)); - } - for (i=0; i 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("txid",creditloop[i].GetHex())); - str[0] = funcid, str[1] = 0; - obj.push_back(Pair("funcid",str)); - if ( funcid == 'R' && createtxid == zeroid ) - { - createtxid = creditloop[i]; - obj.push_back(Pair("issuerpk",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - obj.push_back(Pair("issueraddr",coinaddr)); - GetCCaddress(cp,coinaddr,pk); - obj.push_back(Pair("issuerCCaddr",coinaddr)); - } - else - { - obj.push_back(Pair("receiverpk",HexStr(pk))); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG); - obj.push_back(Pair("receiveraddr",coinaddr)); - GetCCaddress(cp,coinaddr,pk); - obj.push_back(Pair("receiverCCaddr",coinaddr)); - } - Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); - if ( strcmp(destaddr,coinaddr) != 0 ) - { - obj.push_back(Pair("vout0address",destaddr)); - numerrs++; - } - if ( i == 0 && refamount < 0 ) - { - refamount = amount; - refmatures = matures; - result.push_back(Pair("amount",ValueFromAmount(refamount))); - result.push_back(Pair("matures",refmatures)); - } - if ( createtxid != refcreatetxid || amount != refamount || matures != refmatures || currency != refcurrency ) - { - numerrs++; - obj.push_back(Pair("objerror",(char *)"mismatched createtxid or amount or matures or currency")); - obj.push_back(Pair("createtxid",createtxid.GetHex())); - obj.push_back(Pair("amount",ValueFromAmount(amount))); - obj.push_back(Pair("matures",matures)); - obj.push_back(Pair("currency",currency)); - } - a.push_back(obj); - } - } - } - result.push_back(Pair("n",n)); - result.push_back(Pair("numerrors",numerrs)); - result.push_back(Pair("creditloop",a)); - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt find batontxid")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get creditloop")); - } - return(result); -} - -UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr) // [[pk0, shares0], [pk1, shares1], ...] -{ - CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ),a(UniValue::VARR); cJSON *item,*array; std::string rawtx; int32_t i,n; uint8_t buf[33]; CPubKey Marmarapk,pk,poolpk; int64_t payout,poolfee=0,total,totalpayout=0; double poolshares,share,shares = 0.; char *pkstr,*errorstr=0; struct CCcontract_info *cp,C; - poolpk = pubkey2pk(Mypubkey()); - if ( txfee == 0 ) - txfee = 10000; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - if ( (array= cJSON_Parse(jsonstr)) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - for (i=0; i, ]"; - break; - } - } - if ( errorstr == 0 && shares > SMALLVAL ) - { - shares += shares * perc; - if ( (total= AddMarmaraCoinbases(cp,mtx,firstheight,poolpk,60)) > 0 ) - { - for (i=0; i SMALLVAL ) - { - payout = (share * (total - txfee)) / shares; - if ( payout > 0 ) - { - if ( (pkstr= jstr(jitem(item,0),0)) != 0 && strlen(pkstr) == 66 ) - { - UniValue x(UniValue::VOBJ); - totalpayout += payout; - decode_hex(buf,33,pkstr); - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,payout,Marmarapk,buf2pk(buf))); - x.push_back(Pair(pkstr, (double)payout/COIN)); - a.push_back(x); - } - } - } - } - if ( totalpayout > 0 && total > totalpayout-txfee ) - { - poolfee = (total - totalpayout - txfee); - mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,poolfee,Marmarapk,poolpk)); - } - rawtx = FinalizeCCTx(0,cp,mtx,poolpk,txfee,MarmaraCoinbaseOpret('P',firstheight,poolpk)); - if ( rawtx.size() == 0 ) - errorstr = (char *)"couldnt finalize CCtx"; - } else errorstr = (char *)"couldnt find any coinbases to payout"; - } - else if ( errorstr == 0 ) - errorstr = (char *)"no valid shares submitted"; - free(array); - } else errorstr = (char *)"couldnt parse poolshares jsonstr"; - if ( rawtx.size() == 0 || errorstr != 0 ) - { - result.push_back(Pair("result","error")); - if ( errorstr != 0 ) - result.push_back(Pair("error",errorstr)); - } - else - { - result.push_back(Pair("result",(char *)"success")); - result.push_back(Pair("hex",rawtx)); - if ( totalpayout > 0 && total > totalpayout-txfee ) - { - result.push_back(Pair("firstheight",firstheight)); - result.push_back(Pair("lastheight",((firstheight / MARMARA_GROUPSIZE)+1) * MARMARA_GROUPSIZE - 1)); - result.push_back(Pair("total",ValueFromAmount(total))); - result.push_back(Pair("totalpayout",ValueFromAmount(totalpayout))); - result.push_back(Pair("totalshares",shares)); - result.push_back(Pair("poolfee",ValueFromAmount(poolfee))); - result.push_back(Pair("perc",ValueFromAmount((int64_t)(100. * (double)poolfee/totalpayout * COIN)))); - result.push_back(Pair("payouts",a)); - } - } - return(result); -} - -// get all tx, constrain by vout, issuances[] and closed[] - -UniValue MarmaraInfo(CPubKey refpk,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,std::string currency) -{ - CMutableTransaction mtx; std::vector pubkeys; - UniValue result(UniValue::VOBJ),a(UniValue::VARR),b(UniValue::VARR); int32_t i,n,matches; int64_t totalclosed=0,totalamount=0; std::vector issuances,closed; char coinaddr[64]; - CPubKey Marmarapk; struct CCcontract_info *cp,C; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - result.push_back(Pair("result","success")); - Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(Mypubkey())) << OP_CHECKSIG); - result.push_back(Pair("myaddress",coinaddr)); - result.push_back(Pair("normal",ValueFromAmount(CCaddress_balance(coinaddr,0)))); - - GetCCaddress1of2(cp,coinaddr,Marmarapk,Mypubkey()); - result.push_back(Pair("myCCactivated",coinaddr)); - result.push_back(Pair("activated",ValueFromAmount(CCaddress_balance(coinaddr,1)))); - result.push_back(Pair("activated16",ValueFromAmount(AddMarmarainputs(mtx,pubkeys,coinaddr,0,MARMARA_VINS)))); - - GetCCaddress(cp,coinaddr,Mypubkey()); - result.push_back(Pair("myCCaddress",coinaddr)); - result.push_back(Pair("CCutxos",ValueFromAmount(CCaddress_balance(coinaddr,1)))); - - if ( refpk.size() == 33 ) - result.push_back(Pair("issuer",HexStr(refpk))); - if ( currency.size() == 0 ) - currency = (char *)"MARMARA"; - if ( firstheight <= lastheight ) - firstheight = 0, lastheight = (1 << 30); - if ( minamount <= maxamount ) - minamount = 0, maxamount = (1LL << 60); - result.push_back(Pair("firstheight",firstheight)); - result.push_back(Pair("lastheight",lastheight)); - result.push_back(Pair("minamount",ValueFromAmount(minamount))); - result.push_back(Pair("maxamount",ValueFromAmount(maxamount))); - result.push_back(Pair("currency",currency)); - if ( (n= MarmaraGetCreditloops(totalamount,issuances,totalclosed,closed,cp,firstheight,lastheight,minamount,maxamount,refpk,currency)) > 0 ) - { - result.push_back(Pair("n",n)); - matches = (int32_t)issuances.size(); - result.push_back(Pair("pending",matches)); - for (i=0; isize; i++) { sub = subconditions[i]; - if (needed && (fulfillment = asnFulfillmentNew(sub))) { + if (needed && (fulfillment = asnFulfillmentNew(sub)) != NULL) { asn_set_add(&tf->subfulfillments, fulfillment); needed--; } else { diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index b4d961d6e2c..4ac0bd7d410 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -19,7 +19,7 @@ #include #include -#include +#include "cJSON.h" #include "../include/cryptoconditions.h" #include "include/sha256.h" #include "asn/asn_application.h" @@ -216,7 +216,7 @@ void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t * ASN_STRUCT_FREE(*asnType, fp); if (rc.encoded < 1) { fprintf(stderr, "Encoding fingerprint failed\n"); - return 0; + return; } sha256(buf, rc.encoded, out); } diff --git a/src/komodo.cpp b/src/komodo.cpp new file mode 100644 index 00000000000..cf18b0e9489 --- /dev/null +++ b/src/komodo.cpp @@ -0,0 +1,1199 @@ +/****************************************************************************** + * Copyright © 2014-2021 The SuperNET Developers and others. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_globals.h" + +#include "komodo.h" + +int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); // defined in rawtransaction.cpp +void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); // defined in komodo_events.h + +/** + * @param height the new height of the chain + */ +void komodo_currentheight_set(int32_t height) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + sp->CURRENT_HEIGHT = height; +} + +extern struct NSPV_inforesp NSPV_inforesult; + +/**** + * @returns the current height of the chain + */ +int32_t komodo_currentheight() +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( KOMODO_NSPV_SUPERLITE ) + { + return (NSPV_inforesult.height); + } + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + return(sp->CURRENT_HEIGHT); + else return(0); +} + +/*** + * Parse 1 record from the state file + * NOTE: This is a (slower?) alternative to komodo_faststateinit + * @param sp the state + * @param fp the file + * @param symbol the symbol + * @param dest a buffer + * @returns the record type processed or -1 on error + */ +int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest) +{ + static int32_t errs; + int32_t func,ht,notarized_height,num,matched=0,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; + if ( (func= fgetc(fp)) != EOF ) + { + if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + matched = 1; + else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) ) + errs++; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && func != 'T' ) + printf("[%s] matched.%d fpos.%ld func.(%d %c) ht.%d\n",ASSETCHAINS_SYMBOL,matched,ftell(fp),func,func,ht); + if ( func == 'P' ) + { + if ( (num= fgetc(fp)) <= 64 ) + { + if ( fread(pubkeys,33,num,fp) != num ) + errs++; + else + { + //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); + if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) + komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); + } + } else printf("illegal num.%d\n",num); + } + else if ( func == 'N' || func == 'M' ) + { + if ( fread(¬arized_height,1,sizeof(notarized_height),fp) != sizeof(notarized_height) ) + errs++; + if ( fread(¬arized_hash,1,sizeof(notarized_hash),fp) != sizeof(notarized_hash) ) + errs++; + if ( fread(¬arized_desttxid,1,sizeof(notarized_desttxid),fp) != sizeof(notarized_desttxid) ) + errs++; + if ( func == 'M' ) + { + if ( fread(&MoM,1,sizeof(MoM),fp) != sizeof(MoM) ) + errs++; + if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) + errs++; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) + printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); + } + else + { + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; + } + //if ( matched != 0 ) global independent states -> inside *sp + komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); + } + else if ( func == 'U' ) // deprecated + { + uint8_t n,nid; uint256 hash; uint64_t mask; + n = fgetc(fp); + nid = fgetc(fp); + //printf("U %d %d\n",n,nid); + if ( fread(&mask,1,sizeof(mask),fp) != sizeof(mask) ) + errs++; + if ( fread(&hash,1,sizeof(hash),fp) != sizeof(hash) ) + errs++; + //if ( matched != 0 ) + // komodo_eventadd_utxo(sp,symbol,ht,nid,hash,mask,n); + } + else if ( func == 'K' ) + { + int32_t kheight; + if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) + errs++; + //if ( matched != 0 ) global independent states -> inside *sp + //printf("%s.%d load[%s] ht.%d\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight); + komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); + } + else if ( func == 'T' ) + { + int32_t kheight,ktimestamp; + if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) + errs++; + if ( fread(&ktimestamp,1,sizeof(ktimestamp),fp) != sizeof(ktimestamp) ) + errs++; + //if ( matched != 0 ) global independent states -> inside *sp + //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); + komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); + } + else if ( func == 'R' ) + { + uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; + if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) ) + errs++; + if ( fread(&v,1,sizeof(v),fp) != sizeof(v) ) + errs++; + if ( fread(&ovalue,1,sizeof(ovalue),fp) != sizeof(ovalue) ) + errs++; + if ( fread(&olen,1,sizeof(olen),fp) != sizeof(olen) ) + errs++; + if ( olen < sizeof(opret) ) + { + if ( fread(opret,1,olen,fp) != olen ) + errs++; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) + { + int32_t i; for (i=0; i global PAX + } else + { + int32_t i; + for (i=0; i global PVALS + //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); + komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); + //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); + } else printf("error loading pvals[%d]\n",numpvals); + } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); + return(func); + } else return(-1); +} + +/**** + * Read a section of memory + * @param dest the destination + * @param size the size to read + * @param filedata the memory + * @param fposp the position to read from + * @param datalen the size of filedata + * @returns the number of bytes read or -1 on error + */ +int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen) +{ + if ( *fposp+size <= datalen ) + { + memcpy(dest,&filedata[*fposp],size); + (*fposp) += size; + return(size); + } + return(-1); +} + + +/**** + * Parse file to get komodo events + * @param sp the state (stores the events) + * @param filedata the data to parse + * @param fposp the file position + * @param datalen the length of filedata + * @param symbol the currency symbol + * @param dest + * @returns the record type parsed, or number of errors if negative + */ +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) +{ + int32_t errs = 1; // number of errors found + uint8_t rec_type = 0; // type of record found + int32_t ht; // height + bool symbol_matches = false; + long fpos = *fposp; // current position in data stream + + if ( fpos < datalen ) + { + rec_type = filedata[fpos++]; + if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + symbol_matches = true; + else + symbol_matches = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) // get height + errs++; + if ( rec_type == 'P' ) // pubkey record + { + // while we're doing both old and new way + long temp_pos = fpos; + // old way + int32_t num; + if ( (num = filedata[fpos++]) <= 64 ) // number of keys in this record + { + uint8_t pubkeys[64][33]; + if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) + errs++; + else + { + //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); + if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) + komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); + } + } + else + printf("illegal number of keys.%d\n",num); + fpos = temp_pos; + // new way + try + { + std::shared_ptr pubkey = std::make_shared(filedata, fpos, datalen, ht); + if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) + sp->add_event(symbol, ht, pubkey); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } + } + else if ( rec_type == 'N' || rec_type == 'M' ) // notary event + { + // old way + long temp_pos = fpos; + int32_t notarized_height; + if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) + errs++; + uint256 notarized_hash; + if ( memread(¬arized_hash,sizeof(notarized_hash),filedata,&fpos,datalen) != sizeof(notarized_hash) ) + errs++; + uint256 notarized_desttxid; + if ( memread(¬arized_desttxid,sizeof(notarized_desttxid),filedata,&fpos,datalen) != sizeof(notarized_desttxid) ) + errs++; + int32_t MoMdepth; + uint256 MoM; + if ( rec_type == 'M' ) + { + if ( memread(&MoM,sizeof(MoM),filedata,&fpos,datalen) != sizeof(MoM) ) + errs++; + if ( memread(&MoMdepth,sizeof(MoMdepth),filedata,&fpos,datalen) != sizeof(MoMdepth) ) + errs++; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) + printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); + } + else + { + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; + } + komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); + fpos = temp_pos; // reset for new way + // new way + try + { + std::shared_ptr notarized = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'M'); + sp->add_event(symbol, ht, notarized); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } + } + else if ( rec_type == 'U' ) // deprecated + { + uint8_t n,nid; uint256 hash; uint64_t mask; + n = filedata[fpos++]; + nid = filedata[fpos++]; + //printf("U %d %d\n",n,nid); + if ( memread(&mask,sizeof(mask),filedata,&fpos,datalen) != sizeof(mask) ) + errs++; + if ( memread(&hash,sizeof(hash),filedata,&fpos,datalen) != sizeof(hash) ) + errs++; + } + else if ( rec_type == 'K' ) // kmd event + { + long temp_pos = fpos; + // old way + int32_t kheight; + if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) + errs++; + komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); + fpos = temp_pos; // reset for new way + // new way + try + { + std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht); + sp->add_event(symbol, ht, kmd_height); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } + } + else if ( rec_type == 'T' ) // kmd event with timestamp + { + long temp_pos = fpos; + // old way + int32_t kheight,ktimestamp; + if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) + errs++; + if ( memread(&ktimestamp,sizeof(ktimestamp),filedata,&fpos,datalen) != sizeof(ktimestamp) ) + errs++; + //if ( symbol_matches != 0 ) global independent states -> inside *sp + //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); + komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); + fpos = temp_pos; + // new way + try + { + std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'T'); + sp->add_event(symbol, ht, kmd_height); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } + } + else if ( rec_type == 'R' ) // opreturn + { + long temp_pos = fpos; + // old way + uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; + if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) + errs++; + if ( memread(&v,sizeof(v),filedata,&fpos,datalen) != sizeof(v) ) + errs++; + if ( memread(&ovalue,sizeof(ovalue),filedata,&fpos,datalen) != sizeof(ovalue) ) + errs++; + if ( memread(&olen,sizeof(olen),filedata,&fpos,datalen) != sizeof(olen) ) + errs++; + if ( olen < sizeof(opret) ) + { + if ( memread(opret,olen,filedata,&fpos,datalen) != olen ) + errs++; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && symbol_matches ) + { + int32_t i; for (i=0; i global PAX + } else + { + int32_t i; + for (i=0; i opret = std::make_shared(filedata, fpos, datalen, ht); + sp->add_event(symbol, ht, opret); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } + } + else if ( rec_type == 'D' ) + { + printf("unexpected function D[%d]\n",ht); + } + else if ( rec_type == 'V' ) // pricefeed + { + long temp_pos = fpos; + // old way + int32_t numpvals; uint32_t pvals[128]; + numpvals = filedata[fpos++]; + if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && memread(pvals,(int32_t)(sizeof(uint32_t)*numpvals),filedata,&fpos,datalen) == numpvals*sizeof(uint32_t) ) + { + //if ( symbol_matches != 0 ) global shared state -> global PVALS + //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); + komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); + //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); + } else printf("error loading pvals[%d]\n",numpvals); + fpos = temp_pos; + // new way + try + { + std::shared_ptr feed = std::make_shared(filedata, fpos, datalen, ht); + sp->add_event(symbol, ht, feed); + } + catch(const komodo::parse_error& pe) + { + printf("%s\n", pe.what()); + errs++; + } + } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); + *fposp = fpos; + return(rec_type); + } + return -errs; +} + +/**** + * Update state, including persisting to disk + * @param height + * @param notarpubs + * @param numnotaries + * @param notaryid + * @param txhash + * @param voutmask + * @param numvouts + * @param pvals + * @param numpvals + * @param KMDheight + * @param KMDtimestamp + * @param opretvalue + * @param opretbuf + * @param opretlen + * @param vout + * @param MoM + * @param MoMdepth + */ +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts, + uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) +{ + static FILE *fp; + static int32_t errs; + static int32_t didinit; + static uint256 zero; + struct komodo_state *sp; + char fname[512]; + char symbol[KOMODO_ASSETCHAIN_MAXLEN]; + char dest[KOMODO_ASSETCHAIN_MAXLEN]; + int32_t retval; + int32_t ht; + int32_t func; + uint8_t num; + uint8_t pubkeys[64][33]; + if ( didinit == 0 ) + { + portable_mutex_init(&KOMODO_KV_mutex); + portable_mutex_init(&KOMODO_CC_mutex); + didinit = 1; + } + // Get the correct state object + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + { + KOMODO_INITDONE = (uint32_t)time(NULL); + printf("[%s] no komodo_stateptr\n",ASSETCHAINS_SYMBOL); + return; + } + if ( fp == 0 ) + { + // get the state filename and open it + komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); + if ( (fp= fopen(fname,"rb+")) != 0 ) + { + if ( (retval= komodo_faststateinit(sp,fname,symbol,dest)) > 0 ) // try a fast state init + fseek(fp,0,SEEK_END); + else + { + // fast state init failed. Do it the long way. + while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 ) + ; + } + } else fp = fopen(fname,"wb+"); + KOMODO_INITDONE = (uint32_t)time(NULL); + } + if ( height <= 0 ) + { + return; + } + if ( fp != 0 ) // write out funcid, height, other fields, call side effect function + { + if ( KMDheight != 0 ) + { + if ( KMDtimestamp != 0 ) + { + fputc('T',fp); + if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) + errs++; + if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) + errs++; + if ( fwrite(&KMDtimestamp,1,sizeof(KMDtimestamp),fp) != sizeof(KMDtimestamp) ) + errs++; + } + else + { + fputc('K',fp); + if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) + errs++; + if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) + errs++; + } + komodo_eventadd_kmdheight(sp,symbol,height,KMDheight,KMDtimestamp); + } + else if ( opretbuf != 0 && opretlen > 0 ) + { + uint16_t olen = opretlen; + fputc('R',fp); + if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) + errs++; + if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) + errs++; + if ( fwrite(&vout,1,sizeof(vout),fp) != sizeof(vout) ) + errs++; + if ( fwrite(&opretvalue,1,sizeof(opretvalue),fp) != sizeof(opretvalue) ) + errs++; + if ( fwrite(&olen,1,sizeof(olen),fp) != olen ) + errs++; + if ( fwrite(opretbuf,1,olen,fp) != olen ) + errs++; + komodo_eventadd_opreturn(sp,symbol,height,txhash,opretvalue,vout,opretbuf,olen); + } + else if ( notarypubs != 0 && numnotaries > 0 ) + { + printf("ht.%d func P[%d] errs.%d\n",height,numnotaries,errs); + fputc('P',fp); + if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) + errs++; + fputc(numnotaries,fp); + if ( fwrite(notarypubs,33,numnotaries,fp) != numnotaries ) + errs++; + komodo_eventadd_pubkeys(sp,symbol,height,numnotaries,notarypubs); + } + else if ( voutmask != 0 && numvouts > 0 ) + { + fputc('U',fp); + if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) + errs++; + fputc(numvouts,fp); + fputc(notaryid,fp); + if ( fwrite(&voutmask,1,sizeof(voutmask),fp) != sizeof(voutmask) ) + errs++; + if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) + errs++; + } + else if ( pvals != 0 && numpvals > 0 ) + { + int32_t i,nonz = 0; + for (i=0; i<32; i++) + if ( pvals[i] != 0 ) + nonz++; + if ( nonz >= 32 ) + { + fputc('V',fp); + if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) + errs++; + fputc(numpvals,fp); + if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals ) + errs++; + komodo_eventadd_pricefeed(sp,symbol,height,pvals,numpvals); + } + } + else if ( height != 0 ) + { + if ( sp != 0 ) + { + if ( sp->MoMdepth != 0 && sp->MoM != zero ) + fputc('M',fp); + else fputc('N',fp); + if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) + errs++; + if ( fwrite(&sp->NOTARIZED_HEIGHT,1,sizeof(sp->NOTARIZED_HEIGHT),fp) != sizeof(sp->NOTARIZED_HEIGHT) ) + errs++; + if ( fwrite(&sp->NOTARIZED_HASH,1,sizeof(sp->NOTARIZED_HASH),fp) != sizeof(sp->NOTARIZED_HASH) ) + errs++; + if ( fwrite(&sp->NOTARIZED_DESTTXID,1,sizeof(sp->NOTARIZED_DESTTXID),fp) != sizeof(sp->NOTARIZED_DESTTXID) ) + errs++; + if ( sp->MoMdepth != 0 && sp->MoM != zero ) + { + if ( fwrite(&sp->MoM,1,sizeof(sp->MoM),fp) != sizeof(sp->MoM) ) + errs++; + if ( fwrite(&sp->MoMdepth,1,sizeof(sp->MoMdepth),fp) != sizeof(sp->MoMdepth) ) + errs++; + } + komodo_eventadd_notarized(sp,symbol,height,dest,sp->NOTARIZED_HASH,sp->NOTARIZED_DESTTXID,sp->NOTARIZED_HEIGHT,sp->MoM,sp->MoMdepth); + } + } + fflush(fp); + } +} + +/***** + * Validate the chain + * @param srchash + * @param notarized_height + * @returns 0 on failure, 1 on success + */ +int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) +{ + static int32_t last_rewind; int32_t rewindtarget; CBlockIndex *pindex; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + return(0); + if ( IsInitialBlockDownload() == 0 && ((pindex= komodo_getblockindex(srchash)) == 0 || pindex->GetHeight() != notarized_height) ) + { + if ( sp->NOTARIZED_HEIGHT > 0 && sp->NOTARIZED_HEIGHT < notarized_height ) + rewindtarget = sp->NOTARIZED_HEIGHT - 1; + else if ( notarized_height > 101 ) + rewindtarget = notarized_height - 101; + else rewindtarget = 0; + if ( rewindtarget != 0 && rewindtarget > KOMODO_REWIND && rewindtarget > last_rewind ) + { + if ( last_rewind != 0 ) + { + //KOMODO_REWIND = rewindtarget; + fprintf(stderr,"%s FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n",ASSETCHAINS_SYMBOL,notarized_height,srchash.ToString().c_str(),sp->NOTARIZED_HEIGHT,rewindtarget); + } + last_rewind = rewindtarget; + } + return(0); + } else return(1); +} + +/**** + * Update vout + * @param fJustCheck + * @param isratificationp + * @param notaryid + * @param scriptbuf + * @param scriptlen + * @param height + * @param txhash + * @param i + * @param j + * @param voutmaskp + * @param specialtxp + * @param notarizedheightp + * @param value + * @param notarized + * @param signedmask + * @param timestamp + * @returns negative number on error, notaryid on success + */ +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) +{ + static uint256 zero; static FILE *signedfp; + int32_t opretlen,nid,offset,k,MoMdepth,matched,len = 0; uint256 MoM,srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + return(-1); + if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) + { + if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY != 0 ) + { + printf("%s KOMODO_LASTMINED.%d -> %d\n",ASSETCHAINS_SYMBOL,KOMODO_LASTMINED,height); + prevKOMODO_LASTMINED = KOMODO_LASTMINED; + KOMODO_LASTMINED = height; + } + decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); + /*for (k=0; k<33; k++) + printf("%02x",crypto777[k]); + printf(" crypto777 "); + for (k=0; k>>>>>>> "); + } + else if ( komodo_chosennotary(&nid,height,scriptbuf + 1,timestamp) >= 0 ) + { + //printf("found notary.k%d\n",k); + if ( notaryid < 64 ) + { + if ( notaryid < 0 ) + { + notaryid = nid; + *voutmaskp |= (1LL << j); + } + else if ( notaryid != nid ) + { + //for (i=0; i<33; i++) + // printf("%02x",scriptbuf[i+1]); + //printf(" %s mismatch notaryid.%d k.%d\n",ASSETCHAINS_SYMBOL,notaryid,nid); + notaryid = 64; + *voutmaskp = 0; + } + else *voutmaskp |= (1LL << j); + } + } + } + if ( scriptbuf[len++] == 0x6a ) + { + struct komodo_ccdata ccdata; struct komodo_ccdataMoMoM MoMoMdata; + int32_t validated = 0,nameoffset,opoffset = 0; + if ( (opretlen= scriptbuf[len++]) == 0x4c ) + opretlen = scriptbuf[len++]; + else if ( opretlen == 0x4d ) + { + opretlen = scriptbuf[len++]; + opretlen += (scriptbuf[len++] << 8); + } + opoffset = len; + matched = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( strcmp("KMD",(char *)&scriptbuf[len+32 * 2 + 4]) == 0 ) + matched = 1; + } + else + { + if ( scriptbuf[len] == 'K' ) + { + //fprintf(stderr,"i.%d j.%d KV OPRET len.%d %.8f\n",i,j,opretlen,dstr(value)); + komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); + return(-1); + } + if ( strcmp(ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + matched = 1; + } + offset = 32 * (1 + matched) + 4; + nameoffset = (int32_t)strlen((char *)&scriptbuf[len+offset]); + nameoffset++; + memset(&ccdata,0,sizeof(ccdata)); + strncpy(ccdata.symbol,(char *)&scriptbuf[len+offset],sizeof(ccdata.symbol)); + if ( j == 1 && opretlen >= len+offset-opoffset ) + { + memset(&MoMoMdata,0,sizeof(MoMoMdata)); + if ( matched == 0 && signedmask != 0 && bitweight(signedmask) >= KOMODO_MINRATIFY ) + notarized = 1; + if ( strcmp("PIZZA",ccdata.symbol) == 0 || strncmp("TXSCL",ccdata.symbol,5) == 0 || strcmp("BEER",ccdata.symbol) == 0) + notarized = 1; + if ( 0 && opretlen != 149 ) + printf("[%s].%d (%s) matched.%d i.%d j.%d notarized.%d %llx opretlen.%d len.%d offset.%d opoffset.%d\n",ASSETCHAINS_SYMBOL,height,ccdata.symbol,matched,i,j,notarized,(long long)signedmask,opretlen,len,offset,opoffset); + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); + if ( matched != 0 ) + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); + if ( matched != 0 ) + validated = komodo_validate_chain(srchash,*notarizedheightp); + else validated = 1; + // Any notarization that is matched and has a decodable op_return is enough to pay notaries. Otherwise bugs! + if ( fJustCheck && matched != 0 ) + return(-2); + if ( notarized != 0 && validated != 0 ) + { + //sp->NOTARIZED_HEIGHT = *notarizedheightp; + //sp->NOTARIZED_HASH = srchash; + //sp->NOTARIZED_DESTTXID = desttxid; + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; + len += nameoffset; + ccdata.MoMdata.notarized_height = *notarizedheightp; + ccdata.MoMdata.height = height; + ccdata.MoMdata.txi = i; + //printf("nameoffset.%d len.%d + 36 %d opoffset.%d vs opretlen.%d\n",nameoffset,len,len+36,opoffset,opretlen); + if ( len+36-opoffset <= opretlen ) + { + len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&MoM); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(MoMdepth),(uint8_t *)&MoMdepth); + ccdata.MoMdata.MoM = MoM; + ccdata.MoMdata.MoMdepth = MoMdepth & 0xffff; + if ( len+sizeof(ccdata.CCid)-opoffset <= opretlen ) + { + len += iguana_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); + //if ( ((MoMdepth>>16) & 0xffff) != (ccdata.CCid & 0xffff) ) + // fprintf(stderr,"%s CCid mismatch %u != %u\n",ASSETCHAINS_SYMBOL,((MoMdepth>>16) & 0xffff),(ccdata.CCid & 0xffff)); + ccdata.len = sizeof(ccdata.CCid); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + // MoMoM, depth, numpairs, (notarization ht, MoMoM offset) + if ( len+48-opoffset <= opretlen && strcmp(ccdata.symbol,ASSETCHAINS_SYMBOL) == 0 ) + { + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); + len += iguana_rwbignum(0,&scriptbuf[len],sizeof(MoMoMdata.MoMoM),(uint8_t *)&MoMoMdata.MoMoM); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.MoMoMdepth); + len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.numpairs); + MoMoMdata.len += sizeof(MoMoMdata.MoMoM) + sizeof(uint32_t)*4; + if ( len+MoMoMdata.numpairs*8-opoffset == opretlen ) + { + MoMoMdata.pairs = (struct komodo_ccdatapair *)calloc(MoMoMdata.numpairs,sizeof(*MoMoMdata.pairs)); + for (k=0; k *notarizedheightp || (MoMdepth&0xffff) < 0 ) + { + memset(&MoM,0,sizeof(MoM)); + MoMdepth = 0; + } + else + { + komodo_rwccdata(ASSETCHAINS_SYMBOL,1,&ccdata,&MoMoMdata); + if ( matched != 0 ) + printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); + } + if ( MoMoMdata.pairs != 0 ) + free(MoMoMdata.pairs); + memset(&ccdata,0,sizeof(ccdata)); + memset(&MoMoMdata,0,sizeof(MoMoMdata)); + } + else if ( ASSETCHAINS_SYMBOL[0] == 0 && matched != 0 && notarized != 0 && validated != 0 ) + komodo_rwccdata((char *)"KMD",1,&ccdata,0); + + if ( matched != 0 && *notarizedheightp > sp->NOTARIZED_HEIGHT && *notarizedheightp < height ) + { + sp->NOTARIZED_HEIGHT = *notarizedheightp; + sp->NOTARIZED_HASH = srchash; + sp->NOTARIZED_DESTTXID = desttxid; + if ( MoM != zero && (MoMdepth&0xffff) > 0 ) + { + sp->MoM = MoM; + sp->MoMdepth = MoMdepth; + } + komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth); + //if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); + + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( signedfp == 0 ) + { + char fname[512]; + komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); + if ( (signedfp= fopen(fname,"rb+")) == 0 ) + signedfp = fopen(fname,"wb"); + else fseek(signedfp,0,SEEK_END); + } + if ( signedfp != 0 ) + { + fwrite(&height,1,sizeof(height),signedfp); + fwrite(&signedmask,1,sizeof(signedmask),signedfp); + fflush(signedfp); + } + if ( opretlen > len && scriptbuf[len] == 'A' ) + { + //for (i=0; i 600000 && matched != 0 ) + printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n",ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen); + } + else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 ) + { + if ( notaryid >= 0 && notaryid < 64 ) + komodo_paxpricefeed(height,&scriptbuf[len],opretlen); + } + else if ( matched != 0 ) + { + //int32_t k; for (k=0; k= 32*2+4 && strcmp(ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) + { + for (k=0; k<32; k++) + if ( scriptbuf[len+k] != 0 ) + break; + if ( k == 32 ) + { + *isratificationp = 1; + printf("ISRATIFICATION (%s)\n",(char *)&scriptbuf[len+32*2+4]); + } + } + + if ( *isratificationp == 0 && (signedmask != 0 || (scriptbuf[len] != 'X' && scriptbuf[len] != 'A')) ) // && scriptbuf[len] != 'I') + komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); + } + } + return(notaryid); +} + +/*int32_t komodo_isratify(int32_t isspecial,int32_t numvalid) +{ + if ( isspecial != 0 && numvalid >= KOMODO_MINRATIFY ) + return(1); + else return(0); +}*/ + +// Special tx have vout[0] -> CRYPTO777 +// with more than KOMODO_MINRATIFY pay2pubkey outputs -> ratify +// if all outputs to notary -> notary utxo +// if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed +// OP_RETURN: 'D' -> deposit, 'W' -> withdraw + +/**** + * Compare notaries + * @param scirptPubKey + * @param scriptlen + * @param pubkeys + * @param numnotaries + * @param rmd160 + * @returns -1 on failure, 0 or positive number on success + */ +int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) +{ + int32_t i; + if ( scriptlen == 25 && memcmp(&scriptPubKey[3],rmd160,20) == 0 ) + return(0); + else if ( scriptlen == 35 ) + { + for (i=0; i notarisations; + uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; + int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; + if ( pindex == 0 ) + { + fprintf(stderr,"komodo_connectblock null pindex\n"); + return(0); + } + memset(&zero,0,sizeof(zero)); + komodo_init(pindex->GetHeight()); + KOMODO_INITDONE = (uint32_t)time(NULL); + if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) + { + fprintf(stderr,"unexpected null komodostateptr.[%s]\n",ASSETCHAINS_SYMBOL); + return(0); + } + //fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); + // Wallet Filter. Disabled here. Cant be activated by notaries or pools with some changes. + if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || IS_STAKED_NOTARY > -1 ) + { + staked_era = STAKED_era(pindex->GetBlockTime()); + if ( !fJustCheck && staked_era != lastStakedEra ) + { + uint8_t tmp_pubkeys[64][33]; + int8_t numSN = numStakedNotaries(tmp_pubkeys,staked_era); + UpdateNotaryAddrs(tmp_pubkeys,numSN); + STAKED_ERA = staked_era; + lastStakedEra = staked_era; + } + } + numnotaries = komodo_notaries(pubkeys,pindex->GetHeight(),pindex->GetBlockTime()); + calc_rmd160_sha256(rmd160,pubkeys[0],33); + if ( pindex->GetHeight() > hwmheight ) + hwmheight = pindex->GetHeight(); + else + { + if ( pindex->GetHeight() != hwmheight ) + { + printf("%s hwmheight.%d vs pindex->GetHeight().%d t.%u reorg.%d\n",ASSETCHAINS_SYMBOL,hwmheight,pindex->GetHeight(),(uint32_t)pindex->nTime,hwmheight-pindex->GetHeight()); + komodo_purge_ccdata((int32_t)pindex->GetHeight()); + hwmheight = pindex->GetHeight(); + } + if (!fJustCheck) + { + komodo_event_rewind(sp,symbol,pindex->GetHeight()); + komodo_stateupdate(pindex->GetHeight(),0,0,0,zero,0,0,0,0,-pindex->GetHeight(),pindex->nTime,0,0,0,0,zero,0); + } + } + komodo_currentheight_set(chainActive.LastTip()->GetHeight()); + int transaction = 0; + if ( pindex != 0 ) + { + height = pindex->GetHeight(); + txn_count = block.vtx.size(); + for (i=0; i 1 && ASSETCHAINS_NOTARY_PAY[0] != 0 ) + break; + txhash = block.vtx[i].GetHash(); + numvouts = block.vtx[i].vout.size(); + notaryid = -1; + voutmask = specialtx = notarizedheight = isratification = notarized = 0; + signedmask = (height < 91400) ? 1 : 0; + numvins = block.vtx[i].vin.size(); + for (j=0; j 0 ) + { + if ( (k= komodo_notarycmp(scriptPubKey,scriptlen,pubkeys,numnotaries,rmd160)) >= 0 ) + signedmask |= (1LL << k); + else if ( 0 && numvins >= 17 ) + { + int32_t k; + for (k=0; k= KOMODO_MINRATIFY) || + (numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) || + numvalid > (numnotaries/5) ) + { + if ( !fJustCheck && ASSETCHAINS_SYMBOL[0] != 0) + { + static FILE *signedfp; + if ( signedfp == 0 ) + { + char fname[512]; + komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); + if ( (signedfp= fopen(fname,"rb+")) == 0 ) + signedfp = fopen(fname,"wb"); + else fseek(signedfp,0,SEEK_END); + } + if ( signedfp != 0 ) + { + fwrite(&height,1,sizeof(height),signedfp); + fwrite(&signedmask,1,sizeof(signedmask),signedfp); + fflush(signedfp); + } + transaction = i; + printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d <<<<<<<<<<< notarized\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts); + } + notarized = 1; + } + // simulate DPoW in regtest mode for dpowconfs tests/etc + if ( Params().NetworkIDString() == "regtest" && ( height%7 == 0) ) { + notarized = 1; + sp->NOTARIZED_HEIGHT = height; + sp->NOTARIZED_HASH = block.GetHash(); + sp->NOTARIZED_DESTTXID = txhash; + } + for (j=0; j= 235300 && block.vtx[0].vout[1].nValue >= 100000*COIN ) + block.vtx[0].vout[1].nValue = 0; + break; + } + } + }*/ + len = block.vtx[i].vout[j].scriptPubKey.size(); + + if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) + { + memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); + notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime()); + if ( fJustCheck && notaryid == -2 ) + { + // We see a valid notarisation here, save its location. + notarisations.push_back(i); + } + if ( 0 && i > 0 ) + { + for (k=0; k 2 ) + { + numvalid = 0; + memset(pubkeys,0,sizeof(pubkeys)); + for (j=1; j= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) + { + memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); + if ( len == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) + { + memcpy(pubkeys[numvalid++],scriptbuf+1,33); + for (k=0; k<33; k++) + printf("%02x",scriptbuf[k+1]); + printf(" <- new notary.[%d]\n",j-1); + } + } + } + if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 ) + { + if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) + { + memset(&txhash,0,sizeof(txhash)); + komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0); + printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height); + } else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries); + } + } + } + } + if ( !fJustCheck && IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height); + if ( !fJustCheck && pindex->GetHeight() == hwmheight ) + komodo_stateupdate(height,0,0,0,zero,0,0,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0); + } + else + { fprintf(stderr,"komodo_connectblock: unexpected null pindex\n"); return(0); } + //KOMODO_INITDONE = (uint32_t)time(NULL); + //fprintf(stderr,"%s end connect.%d\n",ASSETCHAINS_SYMBOL,pindex->GetHeight()); + if (fJustCheck) + { + if ( notarisations.size() == 0 ) + return(0); + if ( notarisations.size() == 1 && notarisations[0] == 1 ) + return(1); + if ( notarisations.size() > 1 || (notarisations.size() == 1 && notarisations[0] != 1) ) + return(-1); + + fprintf(stderr,"komodo_connectblock: unxexpected behaviour when fJustCheck == true, report blackjok3rtt plz ! \n"); + /* this needed by gcc-8, it counts here that control reaches end of non-void function without this. + by default, we count that if control reached here -> the valid notarization isnt in position 1 or there are too many notarizations in this block. + */ + return(-1); + } + else return(0); +} diff --git a/src/komodo.h b/src/komodo.h index f88886630a3..3e0a99ac1db 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -12,10 +12,10 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once -#ifndef H_KOMODO_H -#define H_KOMODO_H #include "komodo_defs.h" +#include "uint256.h" #include "notaries_staked.h" #ifdef _WIN32 @@ -28,7 +28,6 @@ #define KOMODO_ASSETCHAINS_WAITNOTARIZE #define KOMODO_PAXMAX (10000 * COIN) extern int32_t NOTARIZED_HEIGHT; -uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; #include #include @@ -37,183 +36,42 @@ uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; #include "uthash.h" #include "utlist.h" -int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); -bool check_pprevnotarizedht(); - #include "komodo_structs.h" -#include "komodo_globals.h" #include "komodo_utils.h" #include "komodo_curve25519.h" -#include "komodo_cJSON.c" +#include "komodo_cJSON.h" #include "komodo_bitcoind.h" #include "komodo_interest.h" #include "komodo_pax.h" #include "komodo_notary.h" -int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); #include "komodo_kv.h" #include "komodo_jumblr.h" #include "komodo_gateway.h" #include "komodo_events.h" #include "komodo_ccdata.h" -void komodo_currentheight_set(int32_t height) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - sp->CURRENT_HEIGHT = height; -} - -extern struct NSPV_inforesp NSPV_inforesult; -int32_t komodo_currentheight() -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( KOMODO_NSPV_SUPERLITE ) - { - return (NSPV_inforesult.height); - } - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - return(sp->CURRENT_HEIGHT); - else return(0); -} +/** + * @param height the new height of the chain + */ +void komodo_currentheight_set(int32_t height); -int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest) -{ - static int32_t errs; - int32_t func,ht,notarized_height,num,matched=0,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; - if ( (func= fgetc(fp)) != EOF ) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - matched = 1; - else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && func != 'T' ) - printf("[%s] matched.%d fpos.%ld func.(%d %c) ht.%d\n",ASSETCHAINS_SYMBOL,matched,ftell(fp),func,func,ht); - if ( func == 'P' ) - { - if ( (num= fgetc(fp)) <= 64 ) - { - if ( fread(pubkeys,33,num,fp) != num ) - errs++; - else - { - //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); - } - } else printf("illegal num.%d\n",num); - } - else if ( func == 'N' || func == 'M' ) - { - if ( fread(¬arized_height,1,sizeof(notarized_height),fp) != sizeof(notarized_height) ) - errs++; - if ( fread(¬arized_hash,1,sizeof(notarized_hash),fp) != sizeof(notarized_hash) ) - errs++; - if ( fread(¬arized_desttxid,1,sizeof(notarized_desttxid),fp) != sizeof(notarized_desttxid) ) - errs++; - if ( func == 'M' ) - { - if ( fread(&MoM,1,sizeof(MoM),fp) != sizeof(MoM) ) - errs++; - if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); - } - else - { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - } - //if ( matched != 0 ) global independent states -> inside *sp - komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); - } - else if ( func == 'U' ) // deprecated - { - uint8_t n,nid; uint256 hash; uint64_t mask; - n = fgetc(fp); - nid = fgetc(fp); - //printf("U %d %d\n",n,nid); - if ( fread(&mask,1,sizeof(mask),fp) != sizeof(mask) ) - errs++; - if ( fread(&hash,1,sizeof(hash),fp) != sizeof(hash) ) - errs++; - //if ( matched != 0 ) - // komodo_eventadd_utxo(sp,symbol,ht,nid,hash,mask,n); - } - else if ( func == 'K' ) - { - int32_t kheight; - if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) - errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); - } - else if ( func == 'T' ) - { - int32_t kheight,ktimestamp; - if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) - errs++; - if ( fread(&ktimestamp,1,sizeof(ktimestamp),fp) != sizeof(ktimestamp) ) - errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); - } - else if ( func == 'R' ) - { - uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; - if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) ) - errs++; - if ( fread(&v,1,sizeof(v),fp) != sizeof(v) ) - errs++; - if ( fread(&ovalue,1,sizeof(ovalue),fp) != sizeof(ovalue) ) - errs++; - if ( fread(&olen,1,sizeof(olen),fp) != sizeof(olen) ) - errs++; - if ( olen < sizeof(opret) ) - { - if ( fread(opret,1,olen,fp) != olen ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) - { - int32_t i; for (i=0; i global PAX - } else - { - int32_t i; - for (i=0; i global PVALS - //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); - komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); - //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); - } else printf("error loading pvals[%d]\n",numpvals); - } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); - return(func); - } else return(-1); -} +/**** + * @returns the current height of the chain + */ +int32_t komodo_currentheight(); + +/*** + * Parse 1 record from the state file + * NOTE: This is a (slower?) alternative to komodo_faststateinit + * @param sp the state + * @param fp the file + * @param symbol the symbol + * @param dest a buffer + * @returns the record type processed or -1 on error + */ +int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); /**** * Read a section of memory @@ -224,17 +82,7 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char * @param datalen the size of filedata * @returns the number of bytes read or -1 on error */ -int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen) -{ - if ( *fposp+size <= datalen ) - { - memcpy(dest,&filedata[*fposp],size); - (*fposp) += size; - return(size); - } - return(-1); -} - +int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen); /**** * Parse file to get komodo events @@ -246,544 +94,62 @@ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datal * @param dest * @returns the record type parsed, or number of errors if negative */ -int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) -{ - int32_t errs = 1; // number of errors found - uint8_t rec_type = 0; // type of record found - int32_t ht; // height - bool symbol_matches = false; - long fpos = *fposp; // current position in data stream - - if ( fpos < datalen ) - { - rec_type = filedata[fpos++]; - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - symbol_matches = true; - else - symbol_matches = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) // get height - errs++; - if ( rec_type == 'P' ) // pubkey record - { - try - { - std::shared_ptr pubkey = std::make_shared(filedata, fpos, datalen, ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - sp->add_event(symbol, ht, pubkey); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } - } - else if ( rec_type == 'N' || rec_type == 'M' ) // notary event - { - try - { - std::shared_ptr notarized = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'M'); - sp->add_event(symbol, ht, notarized); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } - } - else if ( rec_type == 'U' ) // deprecated - { - uint8_t n,nid; uint256 hash; uint64_t mask; - n = filedata[fpos++]; - nid = filedata[fpos++]; - //printf("U %d %d\n",n,nid); - if ( memread(&mask,sizeof(mask),filedata,&fpos,datalen) != sizeof(mask) ) - errs++; - if ( memread(&hash,sizeof(hash),filedata,&fpos,datalen) != sizeof(hash) ) - errs++; - } - else if ( rec_type == 'K' ) // kmd event - { - try - { - std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht); - sp->add_event(symbol, ht, kmd_height); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } - } - else if ( rec_type == 'T' ) // kmd event with timestamp - { - try - { - std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'T'); - sp->add_event(symbol, ht, kmd_height); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } - } - else if ( rec_type == 'R' ) // opreturn - { - try - { - std::shared_ptr opret = std::make_shared(filedata, fpos, datalen, ht); - sp->add_event(symbol, ht, opret); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } - } - else if ( rec_type == 'D' ) - { - printf("unexpected function D[%d]\n",ht); - } - else if ( rec_type == 'V' ) // pricefeed - { - try - { - std::shared_ptr feed = std::make_shared(filedata, fpos, datalen, ht); - sp->add_event(symbol, ht, feed); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } - } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); - *fposp = fpos; - return(rec_type); - } - return -errs; -} - -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) -{ - static FILE *fp; static int32_t errs,didinit; static uint256 zero; - struct komodo_state *sp; char fname[512],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t retval,ht,func; uint8_t num,pubkeys[64][33]; - if ( didinit == 0 ) - { - portable_mutex_init(&KOMODO_KV_mutex); - portable_mutex_init(&KOMODO_CC_mutex); - didinit = 1; - } - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - { - KOMODO_INITDONE = (uint32_t)time(NULL); - printf("[%s] no komodo_stateptr\n",ASSETCHAINS_SYMBOL); - return; - } - //printf("[%s] (%s) -> (%s)\n",ASSETCHAINS_SYMBOL,symbol,dest); - if ( fp == 0 ) - { - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); - if ( (fp= fopen(fname,"rb+")) != 0 ) - { - if ( (retval= komodo_faststateinit(sp,fname,symbol,dest)) > 0 ) - fseek(fp,0,SEEK_END); - else - { - fprintf(stderr,"komodo_faststateinit retval.%d\n",retval); - while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 ) - ; - } - } else fp = fopen(fname,"wb+"); - KOMODO_INITDONE = (uint32_t)time(NULL); - } - if ( height <= 0 ) - { - //printf("early return: stateupdate height.%d\n",height); - return; - } - if ( fp != 0 ) // write out funcid, height, other fields, call side effect function - { - //printf("fpos.%ld ",ftell(fp)); - if ( KMDheight != 0 ) - { - if ( KMDtimestamp != 0 ) - { - fputc('T',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) - errs++; - if ( fwrite(&KMDtimestamp,1,sizeof(KMDtimestamp),fp) != sizeof(KMDtimestamp) ) - errs++; - } - else - { - fputc('K',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) - errs++; - } - komodo_eventadd_kmdheight(sp,symbol,height,KMDheight,KMDtimestamp); - } - else if ( opretbuf != 0 && opretlen > 0 ) - { - uint16_t olen = opretlen; - fputc('R',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) - errs++; - if ( fwrite(&vout,1,sizeof(vout),fp) != sizeof(vout) ) - errs++; - if ( fwrite(&opretvalue,1,sizeof(opretvalue),fp) != sizeof(opretvalue) ) - errs++; - if ( fwrite(&olen,1,sizeof(olen),fp) != olen ) - errs++; - if ( fwrite(opretbuf,1,olen,fp) != olen ) - errs++; -//printf("create ht.%d R opret[%d] sp.%p\n",height,olen,sp); - //komodo_opreturn(height,opretvalue,opretbuf,olen,txhash,vout); - komodo_eventadd_opreturn(sp,symbol,height,txhash,opretvalue,vout,opretbuf,olen); - } - else if ( notarypubs != 0 && numnotaries > 0 ) - { - printf("ht.%d func P[%d] errs.%d\n",height,numnotaries,errs); - fputc('P',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numnotaries,fp); - if ( fwrite(notarypubs,33,numnotaries,fp) != numnotaries ) - errs++; - komodo_eventadd_pubkeys(sp,symbol,height,numnotaries,notarypubs); - } - else if ( voutmask != 0 && numvouts > 0 ) - { - //printf("ht.%d func U %d %d errs.%d hashsize.%ld\n",height,numvouts,notaryid,errs,sizeof(txhash)); - fputc('U',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numvouts,fp); - fputc(notaryid,fp); - if ( fwrite(&voutmask,1,sizeof(voutmask),fp) != sizeof(voutmask) ) - errs++; - if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) - errs++; - //komodo_eventadd_utxo(sp,symbol,height,notaryid,txhash,voutmask,numvouts); - } - else if ( pvals != 0 && numpvals > 0 ) - { - int32_t i,nonz = 0; - for (i=0; i<32; i++) - if ( pvals[i] != 0 ) - nonz++; - if ( nonz >= 32 ) - { - fputc('V',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numpvals,fp); - if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals ) - errs++; - komodo_eventadd_pricefeed(sp,symbol,height,pvals,numpvals); - //printf("ht.%d V numpvals[%d]\n",height,numpvals); - } - //printf("save pvals height.%d numpvals.%d\n",height,numpvals); - } - else if ( height != 0 ) - { - //printf("ht.%d func N ht.%d errs.%d\n",height,NOTARIZED_HEIGHT,errs); - if ( sp != 0 ) - { - if ( sp->MoMdepth != 0 && sp->MoM != zero ) - fputc('M',fp); - else fputc('N',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&sp->NOTARIZED_HEIGHT,1,sizeof(sp->NOTARIZED_HEIGHT),fp) != sizeof(sp->NOTARIZED_HEIGHT) ) - errs++; - if ( fwrite(&sp->NOTARIZED_HASH,1,sizeof(sp->NOTARIZED_HASH),fp) != sizeof(sp->NOTARIZED_HASH) ) - errs++; - if ( fwrite(&sp->NOTARIZED_DESTTXID,1,sizeof(sp->NOTARIZED_DESTTXID),fp) != sizeof(sp->NOTARIZED_DESTTXID) ) - errs++; - if ( sp->MoMdepth != 0 && sp->MoM != zero ) - { - if ( fwrite(&sp->MoM,1,sizeof(sp->MoM),fp) != sizeof(sp->MoM) ) - errs++; - if ( fwrite(&sp->MoMdepth,1,sizeof(sp->MoMdepth),fp) != sizeof(sp->MoMdepth) ) - errs++; - } - komodo_eventadd_notarized(sp,symbol,height,dest,sp->NOTARIZED_HASH,sp->NOTARIZED_DESTTXID,sp->NOTARIZED_HEIGHT,sp->MoM,sp->MoMdepth); - } - } - fflush(fp); - } -} +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); -int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) -{ - static int32_t last_rewind; int32_t rewindtarget; CBlockIndex *pindex; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - return(0); - if ( IsInitialBlockDownload() == 0 && ((pindex= komodo_getblockindex(srchash)) == 0 || pindex->GetHeight() != notarized_height) ) - { - if ( sp->NOTARIZED_HEIGHT > 0 && sp->NOTARIZED_HEIGHT < notarized_height ) - rewindtarget = sp->NOTARIZED_HEIGHT - 1; - else if ( notarized_height > 101 ) - rewindtarget = notarized_height - 101; - else rewindtarget = 0; - if ( rewindtarget != 0 && rewindtarget > KOMODO_REWIND && rewindtarget > last_rewind ) - { - if ( last_rewind != 0 ) - { - //KOMODO_REWIND = rewindtarget; - fprintf(stderr,"%s FORK detected. notarized.%d %s not in this chain! last notarization %d -> rewindtarget.%d\n",ASSETCHAINS_SYMBOL,notarized_height,srchash.ToString().c_str(),sp->NOTARIZED_HEIGHT,rewindtarget); - } - last_rewind = rewindtarget; - } - return(0); - } else return(1); -} - -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) -{ - static uint256 zero; static FILE *signedfp; - int32_t opretlen,nid,offset,k,MoMdepth,matched,len = 0; uint256 MoM,srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - return(-1); - if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) - { - if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY != 0 ) - { - printf("%s KOMODO_LASTMINED.%d -> %d\n",ASSETCHAINS_SYMBOL,KOMODO_LASTMINED,height); - prevKOMODO_LASTMINED = KOMODO_LASTMINED; - KOMODO_LASTMINED = height; - } - decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); - /*for (k=0; k<33; k++) - printf("%02x",crypto777[k]); - printf(" crypto777 "); - for (k=0; k>>>>>>> "); - } - else if ( komodo_chosennotary(&nid,height,scriptbuf + 1,timestamp) >= 0 ) - { - //printf("found notary.k%d\n",k); - if ( notaryid < 64 ) - { - if ( notaryid < 0 ) - { - notaryid = nid; - *voutmaskp |= (1LL << j); - } - else if ( notaryid != nid ) - { - //for (i=0; i<33; i++) - // printf("%02x",scriptbuf[i+1]); - //printf(" %s mismatch notaryid.%d k.%d\n",ASSETCHAINS_SYMBOL,notaryid,nid); - notaryid = 64; - *voutmaskp = 0; - } - else *voutmaskp |= (1LL << j); - } - } - } - if ( scriptbuf[len++] == 0x6a ) - { - struct komodo_ccdata ccdata; struct komodo_ccdataMoMoM MoMoMdata; - int32_t validated = 0,nameoffset,opoffset = 0; - if ( (opretlen= scriptbuf[len++]) == 0x4c ) - opretlen = scriptbuf[len++]; - else if ( opretlen == 0x4d ) - { - opretlen = scriptbuf[len++]; - opretlen += (scriptbuf[len++] << 8); - } - opoffset = len; - matched = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( strcmp("KMD",(char *)&scriptbuf[len+32 * 2 + 4]) == 0 ) - matched = 1; - } - else - { - if ( scriptbuf[len] == 'K' ) - { - //fprintf(stderr,"i.%d j.%d KV OPRET len.%d %.8f\n",i,j,opretlen,dstr(value)); - komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); - return(-1); - } - if ( strcmp(ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) - matched = 1; - } - offset = 32 * (1 + matched) + 4; - nameoffset = (int32_t)strlen((char *)&scriptbuf[len+offset]); - nameoffset++; - memset(&ccdata,0,sizeof(ccdata)); - strncpy(ccdata.symbol,(char *)&scriptbuf[len+offset],sizeof(ccdata.symbol)); - if ( j == 1 && opretlen >= len+offset-opoffset ) - { - memset(&MoMoMdata,0,sizeof(MoMoMdata)); - if ( matched == 0 && signedmask != 0 && bitweight(signedmask) >= KOMODO_MINRATIFY ) - notarized = 1; - if ( strcmp("PIZZA",ccdata.symbol) == 0 || strncmp("TXSCL",ccdata.symbol,5) == 0 || strcmp("BEER",ccdata.symbol) == 0) - notarized = 1; - if ( 0 && opretlen != 149 ) - printf("[%s].%d (%s) matched.%d i.%d j.%d notarized.%d %llx opretlen.%d len.%d offset.%d opoffset.%d\n",ASSETCHAINS_SYMBOL,height,ccdata.symbol,matched,i,j,notarized,(long long)signedmask,opretlen,len,offset,opoffset); - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&srchash); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(*notarizedheightp),(uint8_t *)notarizedheightp); - if ( matched != 0 ) - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); - if ( matched != 0 ) - validated = komodo_validate_chain(srchash,*notarizedheightp); - else validated = 1; - // Any notarization that is matched and has a decodable op_return is enough to pay notaries. Otherwise bugs! - if ( fJustCheck && matched != 0 ) - return(-2); - if ( notarized != 0 && validated != 0 ) - { - //sp->NOTARIZED_HEIGHT = *notarizedheightp; - //sp->NOTARIZED_HASH = srchash; - //sp->NOTARIZED_DESTTXID = desttxid; - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - len += nameoffset; - ccdata.MoMdata.notarized_height = *notarizedheightp; - ccdata.MoMdata.height = height; - ccdata.MoMdata.txi = i; - //printf("nameoffset.%d len.%d + 36 %d opoffset.%d vs opretlen.%d\n",nameoffset,len,len+36,opoffset,opretlen); - if ( len+36-opoffset <= opretlen ) - { - len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&MoM); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(MoMdepth),(uint8_t *)&MoMdepth); - ccdata.MoMdata.MoM = MoM; - ccdata.MoMdata.MoMdepth = MoMdepth & 0xffff; - if ( len+sizeof(ccdata.CCid)-opoffset <= opretlen ) - { - len += iguana_rwnum(0,&scriptbuf[len],sizeof(ccdata.CCid),(uint8_t *)&ccdata.CCid); - //if ( ((MoMdepth>>16) & 0xffff) != (ccdata.CCid & 0xffff) ) - // fprintf(stderr,"%s CCid mismatch %u != %u\n",ASSETCHAINS_SYMBOL,((MoMdepth>>16) & 0xffff),(ccdata.CCid & 0xffff)); - ccdata.len = sizeof(ccdata.CCid); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - // MoMoM, depth, numpairs, (notarization ht, MoMoM offset) - if ( len+48-opoffset <= opretlen && strcmp(ccdata.symbol,ASSETCHAINS_SYMBOL) == 0 ) - { - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdstarti); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.kmdendi); - len += iguana_rwbignum(0,&scriptbuf[len],sizeof(MoMoMdata.MoMoM),(uint8_t *)&MoMoMdata.MoMoM); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.MoMoMdepth); - len += iguana_rwnum(0,&scriptbuf[len],sizeof(uint32_t),(uint8_t *)&MoMoMdata.numpairs); - MoMoMdata.len += sizeof(MoMoMdata.MoMoM) + sizeof(uint32_t)*4; - if ( len+MoMoMdata.numpairs*8-opoffset == opretlen ) - { - MoMoMdata.pairs = (struct komodo_ccdatapair *)calloc(MoMoMdata.numpairs,sizeof(*MoMoMdata.pairs)); - for (k=0; k *notarizedheightp || (MoMdepth&0xffff) < 0 ) - { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - } - else - { - komodo_rwccdata(ASSETCHAINS_SYMBOL,1,&ccdata,&MoMoMdata); - if ( matched != 0 ) - printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); - } - if ( MoMoMdata.pairs != 0 ) - free(MoMoMdata.pairs); - memset(&ccdata,0,sizeof(ccdata)); - memset(&MoMoMdata,0,sizeof(MoMoMdata)); - } - else if ( ASSETCHAINS_SYMBOL[0] == 0 && matched != 0 && notarized != 0 && validated != 0 ) - komodo_rwccdata((char *)"KMD",1,&ccdata,0); - - if ( matched != 0 && *notarizedheightp > sp->NOTARIZED_HEIGHT && *notarizedheightp < height ) - { - sp->NOTARIZED_HEIGHT = *notarizedheightp; - sp->NOTARIZED_HASH = srchash; - sp->NOTARIZED_DESTTXID = desttxid; - if ( MoM != zero && (MoMdepth&0xffff) > 0 ) - { - sp->MoM = MoM; - sp->MoMdepth = MoMdepth; - } - komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth); - //if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth); - - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( signedfp == 0 ) - { - char fname[512]; - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); - if ( (signedfp= fopen(fname,"rb+")) == 0 ) - signedfp = fopen(fname,"wb"); - else fseek(signedfp,0,SEEK_END); - } - if ( signedfp != 0 ) - { - fwrite(&height,1,sizeof(height),signedfp); - fwrite(&signedmask,1,sizeof(signedmask),signedfp); - fflush(signedfp); - } - if ( opretlen > len && scriptbuf[len] == 'A' ) - { - //for (i=0; i 600000 && matched != 0 ) - printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n",ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen); - } - else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 ) - { - if ( notaryid >= 0 && notaryid < 64 ) - komodo_paxpricefeed(height,&scriptbuf[len],opretlen); - } - else if ( matched != 0 ) - { - //int32_t k; for (k=0; k= 32*2+4 && strcmp(ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) - { - for (k=0; k<32; k++) - if ( scriptbuf[len+k] != 0 ) - break; - if ( k == 32 ) - { - *isratificationp = 1; - printf("ISRATIFICATION (%s)\n",(char *)&scriptbuf[len+32*2+4]); - } - } +/**** + * Update state, including persisting to disk + * @param height + * @param notarpubs + * @param numnotaries + * @param notaryid + * @param txhash + * @param voutmask + * @param numvouts + * @param pvals + * @param numpvals + * @param KMDheight + * @param KMDtimestamp + * @param opretvalue + * @param opretbuf + * @param opretlen + * @param vout + * @param MoM + * @param MoMdepth + */ +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts, + uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t + opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); + +/***** + * Validate the chain + * @param srchash + * @param notarized_height + * @returns 0 on failure, 1 on success + */ +int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height); - if ( *isratificationp == 0 && (signedmask != 0 || (scriptbuf[len] != 'X' && scriptbuf[len] != 'A')) ) // && scriptbuf[len] != 'I') - komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0); - } - } - return(notaryid); -} +/**** + * Update vout + * @param fJustCheck + * @param isratificationp + * @param notaryid + * @param scriptbuf + * @param scriptlen + * @param height + * @param txhash + * @param i + * @param j + * @param voutmaskp + * @param specialtxp + * @param notarizedheightp + * @param value + * @param notarized + * @param signedmask + * @param timestamp + * @returns negative number on error, notaryid on success + */ +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); /*int32_t komodo_isratify(int32_t isspecial,int32_t numvalid) { @@ -798,257 +164,21 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed // OP_RETURN: 'D' -> deposit, 'W' -> withdraw -int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); - -int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) -{ - int32_t i; - if ( scriptlen == 25 && memcmp(&scriptPubKey[3],rmd160,20) == 0 ) - return(0); - else if ( scriptlen == 35 ) - { - for (i=0; i notarisations; - uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash; - int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; - if ( pindex == 0 ) - { - fprintf(stderr,"komodo_connectblock null pindex\n"); - return(0); - } - memset(&zero,0,sizeof(zero)); - komodo_init(pindex->GetHeight()); - KOMODO_INITDONE = (uint32_t)time(NULL); - if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) - { - fprintf(stderr,"unexpected null komodostateptr.[%s]\n",ASSETCHAINS_SYMBOL); - return(0); - } - //fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); - // Wallet Filter. Disabled here. Cant be activated by notaries or pools with some changes. - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || IS_STAKED_NOTARY > -1 ) - { - staked_era = STAKED_era(pindex->GetBlockTime()); - if ( !fJustCheck && staked_era != lastStakedEra ) - { - uint8_t tmp_pubkeys[64][33]; - int8_t numSN = numStakedNotaries(tmp_pubkeys,staked_era); - UpdateNotaryAddrs(tmp_pubkeys,numSN); - STAKED_ERA = staked_era; - lastStakedEra = staked_era; - } - } - numnotaries = komodo_notaries(pubkeys,pindex->GetHeight(),pindex->GetBlockTime()); - calc_rmd160_sha256(rmd160,pubkeys[0],33); - if ( pindex->GetHeight() > hwmheight ) - hwmheight = pindex->GetHeight(); - else - { - if ( pindex->GetHeight() != hwmheight ) - { - printf("%s hwmheight.%d vs pindex->GetHeight().%d t.%u reorg.%d\n",ASSETCHAINS_SYMBOL,hwmheight,pindex->GetHeight(),(uint32_t)pindex->nTime,hwmheight-pindex->GetHeight()); - komodo_purge_ccdata((int32_t)pindex->GetHeight()); - hwmheight = pindex->GetHeight(); - } - if (!fJustCheck) - { - komodo_event_rewind(sp,symbol,pindex->GetHeight()); - komodo_stateupdate(pindex->GetHeight(),0,0,0,zero,0,0,0,0,-pindex->GetHeight(),pindex->nTime,0,0,0,0,zero,0); - } - } - komodo_currentheight_set(chainActive.LastTip()->GetHeight()); - int transaction = 0; - if ( pindex != 0 ) - { - height = pindex->GetHeight(); - txn_count = block.vtx.size(); - for (i=0; i 1 && ASSETCHAINS_NOTARY_PAY[0] != 0 ) - break; - txhash = block.vtx[i].GetHash(); - numvouts = block.vtx[i].vout.size(); - notaryid = -1; - voutmask = specialtx = notarizedheight = isratification = notarized = 0; - signedmask = (height < 91400) ? 1 : 0; - numvins = block.vtx[i].vin.size(); - for (j=0; j 0 ) - { - if ( (k= komodo_notarycmp(scriptPubKey,scriptlen,pubkeys,numnotaries,rmd160)) >= 0 ) - signedmask |= (1LL << k); - else if ( 0 && numvins >= 17 ) - { - int32_t k; - for (k=0; k= KOMODO_MINRATIFY) || - (numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) || - numvalid > (numnotaries/5) ) - { - if ( !fJustCheck && ASSETCHAINS_SYMBOL[0] != 0) - { - static FILE *signedfp; - if ( signedfp == 0 ) - { - char fname[512]; - komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"signedmasks"); - if ( (signedfp= fopen(fname,"rb+")) == 0 ) - signedfp = fopen(fname,"wb"); - else fseek(signedfp,0,SEEK_END); - } - if ( signedfp != 0 ) - { - fwrite(&height,1,sizeof(height),signedfp); - fwrite(&signedmask,1,sizeof(signedmask),signedfp); - fflush(signedfp); - } - transaction = i; - printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d <<<<<<<<<<< notarized\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts); - } - notarized = 1; - } - // simulate DPoW in regtest mode for dpowconfs tests/etc - if ( Params().NetworkIDString() == "regtest" && ( height%7 == 0) ) { - notarized = 1; - sp->NOTARIZED_HEIGHT = height; - sp->NOTARIZED_HASH = block.GetHash(); - sp->NOTARIZED_DESTTXID = txhash; - } - //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - // printf("(tx.%d: ",i); - for (j=0; j= 235300 && block.vtx[0].vout[1].nValue >= 100000*COIN ) - block.vtx[0].vout[1].nValue = 0; - break; - } - } - }*/ - //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - // printf("%.8f ",dstr(block.vtx[i].vout[j].nValue)); - len = block.vtx[i].vout[j].scriptPubKey.size(); - - if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) - { - memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); - notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime()); - if ( fJustCheck && notaryid == -2 ) - { - // We see a valid notarisation here, save its location. - notarisations.push_back(i); - } - if ( 0 && i > 0 ) - { - for (k=0; k 2 ) - { - numvalid = 0; - memset(pubkeys,0,sizeof(pubkeys)); - for (j=1; j= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) - { - memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len); - if ( len == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) - { - memcpy(pubkeys[numvalid++],scriptbuf+1,33); - for (k=0; k<33; k++) - printf("%02x",scriptbuf[k+1]); - printf(" <- new notary.[%d]\n",j-1); - } - } - } - if ( ASSETCHAINS_SYMBOL[0] != 0 || height < 100000 ) - { - if ( ((signedmask & 1) != 0 && numvalid >= KOMODO_MINRATIFY) || bitweight(signedmask) > (numnotaries/3) ) - { - memset(&txhash,0,sizeof(txhash)); - komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0,0,zero,0); - printf("RATIFIED! >>>>>>>>>> new notaries.%d newheight.%d from height.%d\n",numvalid,(((height+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,height); - } else printf("signedmask.%llx numvalid.%d wt.%d numnotaries.%d\n",(long long)signedmask,numvalid,bitweight(signedmask),numnotaries); - } - } - } - } - if ( !fJustCheck && IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height); - if ( !fJustCheck && pindex->GetHeight() == hwmheight ) - komodo_stateupdate(height,0,0,0,zero,0,0,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0); - } - else - { fprintf(stderr,"komodo_connectblock: unexpected null pindex\n"); return(0); } - //KOMODO_INITDONE = (uint32_t)time(NULL); - //fprintf(stderr,"%s end connect.%d\n",ASSETCHAINS_SYMBOL,pindex->GetHeight()); - if (fJustCheck) - { - if ( notarisations.size() == 0 ) - return(0); - if ( notarisations.size() == 1 && notarisations[0] == 1 ) - return(1); - if ( notarisations.size() > 1 || (notarisations.size() == 1 && notarisations[0] != 1) ) - return(-1); - - fprintf(stderr,"komodo_connectblock: unxexpected behaviour when fJustCheck == true, report blackjok3rtt plz ! \n"); - /* this needed by gcc-8, it counts here that control reaches end of non-void function without this. - by default, we count that if control reached here -> the valid notarization isnt in position 1 or there are too many notarizations in this block. - */ - return(-1); - } - else return(0); -} +/**** + * Compare notaries + * @param scirptPubKey + * @param scriptlen + * @param pubkeys + * @param numnotaries + * @param rmd160 + * @returns -1 on failure, 0 or positive number on success + */ +int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]); -#endif +/**** + * @param fJustCheck + * @param pindex + * @param block + * @returns positive number on success, -1 or 0 on error + */ +int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); diff --git a/src/komodo_bitcoind.cpp b/src/komodo_bitcoind.cpp new file mode 100644 index 00000000000..274181aef89 --- /dev/null +++ b/src/komodo_bitcoind.cpp @@ -0,0 +1,2842 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ + +// komodo functions that interact with bitcoind C++ +#include "komodo_notary.h" // for komodo_init() +#include "komodo_globals.h" // for KMD_PORT, BTCUSERPASS + +#include "komodo_bitcoind.h" + +const char *LOG_KOMODOBITCOIND = "komodostaking"; + +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); // defined in komodo_notary.h +int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); // defined in komodo_notary.h +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); // declared in komodo.h +unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); // declared in pow.h +bool EnsureWalletIsAvailable(bool avoidException); // declared in rpcwallet.h +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); // defined in komodo_interest.h +CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); // defined in main.h + +extern bool fRequestShutdown; +extern CScript KOMODO_EARLYTXID_SCRIPTPUB; + +uint32_t komodo_heightstamp(int32_t height); + +// 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) + + +/************************************************************************ + * + * 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(); + } + s->ptr[0] = '\0'; +} + +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() ); + } + + 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,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); + } + return nHeight; +} + +// hash value to string for logging +static std::string hash2str(arith_uint256 hashval, int nbits) +{ + std::ostringstream os; + + if (nbits < 8) + nbits = 8; + if (nbits > 32) + nbits = 32; + + for (int32_t i = 31; i >= (31 - nbits + 1); i--) + os << std::setw(2) << std::hex << std::setfill('0') << (int)((uint8_t *)&hashval)[i]; + return os.str(); +} + +/************************************************************************ + * + * 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(); + } + memcpy(s->ptr+s->len,ptr,size*nmemb); + s->ptr[new_len] = '\0'; + s->len = new_len; + return(size * nmemb); +} + + + +/************************************************************************ + * + * 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; itype&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL ) + { + if ( strcmp(command,"signrawtransaction") != 0 ) + printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr); + } + free(rpcstr); + } else retstr = rpcstr; + free_json(json); + //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); + return(retstr); +} +#endif + +/************************************************************************ + * + * perform the query + * + ************************************************************************/ + +char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) +{ + static int didinit,count,count2; static double elapsedsum,elapsedsum2; + struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; + char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; + if ( didinit == 0 ) + { + didinit = 1; + curl_global_init(CURL_GLOBAL_ALL); //init the curl session + } + numretries = 0; + if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 ) + specialcase = 1; + else specialcase = 0; + if ( url[0] == 0 ) + strcpy(url,"http://127.0.0.1:7876/nxt"); + if ( specialcase != 0 && 0 ) + printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); +try_again: + if ( retstrp != 0 ) + *retstrp = 0; + starttime = OS_milliseconds(); + curl_handle = curl_easy_init(); + init_string(&s); + headers = curl_slist_append(0,"Expect:"); + + curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); + curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl_handle,CURLOPT_URL, url); + curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function + 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 + //curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + //curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2); + + 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 + } + 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 *)"]"; + } + + databuf = (char *)malloc(256 + strlen(command) + strlen(params)); + sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); + //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf); + // + } //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 ) + { + fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); + free(s.ptr); + return(0); + } + else if ( numretries >= 1 ) + { + fprintf(stderr,"Maximum number of retries exceeded!\n"); + free(s.ptr); + return(0); + } + if ( (rand() % 1000) == 0 ) + printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); + free(s.ptr); + sleep((1< (%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); +} + +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; + mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1)); + 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); +} + +char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3) +{ + struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0; + if ( (cHandle= *cHandlep) == NULL ) + *cHandlep = cHandle = curl_easy_init(); + else curl_easy_reset(cHandle); + //#ifdef DEBUG + //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1); + //#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); + if ( userpass != 0 && userpass[0] != 0 ) + curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass); + if ( postfields != 0 && postfields[0] != 0 ) + { + curl_easy_setopt(cHandle,CURLOPT_POST,1); + curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields); + } + 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); +} + +char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) +{ + //static void *cHandle; + char url[512],*retstr=0,*retstr2=0,postdata[8192]; + if ( params == 0 || params[0] == 0 ) + params = (char *)"[]"; + if ( strlen(params) < sizeof(postdata)-128 ) + { + sprintf(url,(char *)"http://127.0.0.1:%u",port); + sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); + retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); + } + return(retstr2); +} + +int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp) +{ + char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0; + params[0] = 0; + *kmdnotarized_heightp = 0; + if ( strcmp(dest,"KMD") == 0 ) + { + port = KMD_PORT; + userpass = KMDUSERPASS; + } + else if ( strcmp(dest,"BTC") == 0 ) // this is no longer strictly BTC; depends on -notary= path + { + port = DEST_PORT; + userpass = BTCUSERPASS; + } + else return(0); + if ( userpass[0] != 0 ) + { + if ( strcmp("BTC",dest) != 0 ) + { + if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 ) + { + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (item= jobj(json,(char *)"result")) != 0 ) + { + height = jint(item,(char *)"blocks"); + *kmdnotarized_heightp = height; + } + free_json(json); + } + free(jsonstr); + } + } else { + if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getblockchaininfo",params,port)) != 0 ) + { + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (item= jobj(json,(char *)"result")) != 0 ) + { + height = jint(item,(char *)"blocks"); + *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height; + } + free_json(json); + } + free(jsonstr); + } + } + sprintf(params,"[\"%s\", 1]",txidstr); + if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 ) + { + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (item= jobj(json,(char *)"result")) != 0 ) + { + txid_confirmations = jint(item,(char *)"rawconfirmations"); + if ( txid_confirmations > 0 && height > txid_confirmations ) + txid_height = height - txid_confirmations; + else txid_height = height; + } + free_json(json); + } + free(jsonstr); + } + } + return(txid_height); +} + + +int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 notarized_hash) +{ + int32_t i; uint256 hash; char params[256]; + for (i=0; i<32; i++) + ((uint8_t *)&hash)[i] = script[2+i]; + if ( hash == notarized_hash ) + return(1); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)¬arized_hash)[i]); + printf(" notarized, "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&hash)[i]); + printf(" opreturn from [%s] ht.%d MISMATCHED\n",ASSETCHAINS_SYMBOL,height); + return(-1); +} + +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 ) + { + free(jsonstr); + } +} + +int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 notarized_hash,uint256 notarized_desttxid) +{ + char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; + script = _script; + sprintf(params,"[\"%s\", 1]",notarized_desttxid.ToString().c_str()); + if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) + return(0); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT); + if ( strcmp(dest,"KMD") == 0 ) + { + if ( KMDUSERPASS[0] != 0 ) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); + } + } + else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok + } + else if ( strcmp(dest,"BTC") == 0 ) + { + if ( BTCUSERPASS[0] != 0 ) + { + jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,DEST_PORT); + } + else return(0); + } + else + { + printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest); + return(-1); + } + if ( jsonstr != 0 ) + { + if ( (json= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 ) + { + vout = jitem(vouts,n-1); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + printf("vout.(%s)\n",jprint(vout,0)); + if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 ) + { + if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) + { + //printf("HEX.(%s) vs hash.%s\n",hexstr,notarized_hash.ToString().c_str()); + len = strlen(hexstr) >> 1; + decode_hex(script,len,hexstr); + if ( script[1] == 0x4c ) + { + script++; + len--; + } + else if ( script[1] == 0x4d ) + { + script += 2; + len -= 2; + } + retval = komodo_verifynotarizedscript(height,script,len,notarized_hash); + } + } + } + free_json(txjson); + } + free(jsonstr); + } + return(retval); +} + +CScript komodo_makeopret(CBlock *pblock, bool fNew) +{ + std::vector 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); +} + +uint64_t komodo_seed(int32_t height) +{ + uint64_t seed = (height << 13) ^ (height << 2); + seed <<= 21; + seed |= (height & 0xffffffff); + seed ^= (seed << 17) ^ (seed << 1); + return seed; +} + +// get previous staking utxo opret, address and txtime +uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) +{ + CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts; + *valuep = 0; + if (!GetTransaction(hash, tx, hashBlock, true)) + { + return(0); + } + numvouts = tx.vout.size(); + + if (n < numvouts) + { + *valuep = tx.vout[n].nValue; + opret = tx.vout[numvouts-1].scriptPubKey; + + if (ExtractDestination(tx.vout[n].scriptPubKey, address)) + { + strcpy(destaddr, CBitcoinAddress(address).ToString().c_str()); + LogPrint(LOG_KOMODOBITCOIND, "%s in stake tx found opret and destaddr=%s\n", __func__, destaddr); + } + } + return(tx.nLockTime); +} + +CBlockIndex *komodo_getblockindex(uint256 hash) +{ + BlockMap::const_iterator it = mapBlockIndex.find(hash); + return((it != mapBlockIndex.end()) ? it->second : NULL); +} + +// Extension point to add preferences for stakes (dimxy) +// TODO: what if for some chain several chain's params require different multipliers. Which to select, max? +static int32_t GetStakeMultiplier(CTransaction &tx, int32_t nvout) +{ + int32_t multiplier = 1; // default value + + CAmount nValue = (nvout >= 0 && nvout < tx.vout.size() ? tx.vout[nvout].nValue : -1); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "stake multiplier=" << multiplier << " nValue=" << nValue << std::endl); + return multiplier; +} + +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, hashBlock, true)) + { + fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); // TODO: comment + return(0); + } + if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) + 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() ) + { + int32_t stakemultiplier = GetStakeMultiplier(tx, n); + *valuep = tx.vout[n].nValue * stakemultiplier; + + if (ExtractDestination(tx.vout[n].scriptPubKey, address)) + strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); + } + return(txtime); +} + +CScript EncodeStakingOpRet(uint256 merkleroot) +{ + CScript opret; uint8_t evalcode = 77; + opret << OP_RETURN << E_MARSHAL(ss << evalcode << merkleroot); + return(opret); +} + +uint8_t DecodeStakingOpRet(CScript scriptPubKey, uint256 &merkleroot) +{ + std::vector vopret; uint8_t evalcode; + GetOpReturnData(scriptPubKey, vopret); + if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> evalcode; ss >> merkleroot) != 0 && evalcode == 77 ) + { + //fprintf(stderr, "evalcode.%i merkleroot.%s\n",evalcode, merkleroot.GetHex().c_str() ); + return(1); + } + return(0); +} + +int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp) +{ + if ( timestamp > nStakedDecemberHardforkTimestamp || komodo_heightstamp(height) > nStakedDecemberHardforkTimestamp ) //December 2019 hardfork + return(1); + else return(0); +} + +int32_t komodo_hasOpRet(int32_t height, uint32_t timestamp) +{ + return((komodo_newStakerActive(height, timestamp) == 1)); +} + +bool komodo_checkopret(CBlock *pblock, CScript &merkleroot) +{ + merkleroot = pblock->vtx.back().vout.back().scriptPubKey; + return(merkleroot.IsOpReturn() && merkleroot == komodo_makeopret(pblock, false)); +} + +bool komodo_hardfork_active(uint32_t time) +{ + return ( (ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Height() > nDecemberHardforkHeight) || (ASSETCHAINS_SYMBOL[0] != 0 && time > nStakedDecemberHardforkTimestamp) ); //December 2019 hardfork +} + +uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey) +{ + std::vector vLeaves; + // rereate coinbase tx + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = fNew ? (CScript() << nHeight << CScriptNum(1)) + COINBASE_FLAGS : pblock->vtx[0].vin[0].scriptSig; + txNew.vout.resize(1); + txNew.vout[0].scriptPubKey = scriptPubKey; + txNew.vout[0].nValue = 0; + txNew.nExpiryHeight = 0; + txNew.nLockTime = 0; + //fprintf(stderr, "validation: coinbasetx.%s\n", EncodeHexTx(txNew).c_str()); + //fprintf(stderr, "txnew.%s\n", txNew.GetHash().ToString().c_str()); + vLeaves.push_back(txNew.GetHash()); + vLeaves.push_back(prevBlockHash); + for (int32_t i = 1; i < pblock->vtx.size()-(fNew ? 0 : 1); i++) + vLeaves.push_back(pblock->vtx[i].GetHash()); + return GetMerkleRoot(vLeaves); +} + + +// checks if block is PoS: +// last tx should point to the previous staking utxo (that is spent to self) +// returns 1 if this is PoS block and 0 if false +int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout) +{ + int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid, merkleroot; CScript prevTxOpret; + if ( ASSETCHAINS_STAKED != 0 ) + { + n = pblock->vtx.size(); + + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht." << height << " check for PoS numtx." << n << " numvins." << pblock->vtx[n-1].vin.size() << " numvouts." << pblock->vtx[n-1].vout.size() << std::endl); + if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) + { + // get previous tx and check if it was spent to self + txid = pblock->vtx[n-1].vin[0].prevout.hash; + vout = pblock->vtx[n-1].vin[0].prevout.n; + txtime = komodo_txtime(prevTxOpret, &value, txid, vout, destaddr); // get previous stake tx opret and addr + if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) // get current tx vout address + { + if ( addressout != 0 ) *addressout = voutaddress; + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "check voutaddr." << voutaddr << " vs prevtx destaddr." << destaddr << std::endl); + if ( komodo_newStakerActive(height, pblock->nTime) != 0 ) + { + if ( DecodeStakingOpRet(pblock->vtx[n-1].vout[1].scriptPubKey, merkleroot) != 0 && komodo_calcmerkleroot(pblock, pblock->hashPrevBlock, height, false, pblock->vtx[0].vout[0].scriptPubKey) == merkleroot ) + { + return(1); + } + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "ht=" << height << " incorrect stake tx (komodo_calcmerkleroot failed)" << std::endl); + } + else + { + if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 ) + { + return(1); + } + else + { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " incorrect stake tx (value or destaddr not matched)" << std::endl); + } + } + } + else + { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " not a stake tx (couldn't ExtractDestination)" << std::endl); + } + } + else + { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " not a stake tx (n, vin.size or vout.size not matched)" << std::endl); + } + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " return=0" << std::endl); + } + return(0); +} + +void komodo_disconnect(CBlockIndex *pindex,CBlock& block) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + //fprintf(stderr,"disconnect ht.%d\n",pindex->GetHeight()); + komodo_init(pindex->GetHeight()); + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + //sp->rewinding = pindex->GetHeight(); + //fprintf(stderr,"-%d ",pindex->GetHeight()); + } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->GetHeight(),ASSETCHAINS_SYMBOL); +} + +int32_t komodo_is_notarytx(const CTransaction& tx) +{ + uint8_t *ptr; static uint8_t crypto777[33]; + if ( tx.vout.size() > 0 ) + { + ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0]; + if ( ptr != 0 ) + { + if ( crypto777[0] == 0 ) + decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); + if ( memcmp(ptr+1,crypto777,33) == 0 ) + { + //printf("found notarytx\n"); + return(1); + } + } + } + return(0); +} + +int32_t komodo_block2height(CBlock *block) +{ + 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 ) + { + height2 = (int32_t)pindex->GetHeight(); + if ( height2 >= 0 ) + return(height2); + } + if ( pindex && block != 0 && block->vtx[0].vin.size() > 0 ) + { + ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0]; + if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 ) + { + //for (i=0; i<6; i++) + // printf("%02x",ptr[i]); + n = ptr[0]; + for (i=0; ivtx[0].vin[0].scriptSig.size(),height); + } + //komodo_init(height); + } + if ( height != height2 ) + { + //fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch); + mismatch++; + if ( height2 >= 0 ) + height = height2; + } else match++; + return(height); +} + +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) +{ + int32_t n; + if ( KOMODO_LOADINGBLOCKS == 0 ) + memset(pubkey33,0xff,33); + else memset(pubkey33,0,33); + if ( block->vtx[0].vout.size() > 0 ) + { + txnouttype whichType; + std::vector> vch = std::vector>(); + if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY) + { + CPubKey pubKey(vch[0]); + if (pubKey.IsValid()) + { + memcpy(pubkey33,vch[0].data(),33); + return true; + } + else memset(pubkey33,0,33); + } + else memset(pubkey33,0,33); + } + return(0); +} + +int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) +{ + 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); +} + +uint32_t komodo_chainactive_timestamp() +{ + if ( chainActive.LastTip() != 0 ) + return((uint32_t)chainActive.LastTip()->GetBlockTime()); + else return(0); +} + +CBlockIndex *komodo_chainactive(int32_t height) +{ + if ( chainActive.LastTip() != 0 ) + { + if ( height <= chainActive.LastTip()->GetHeight() ) + return(chainActive[height]); + // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->GetHeight()); + } + //fprintf(stderr,"komodo_chainactive null chainActive.LastTip() height %d\n",height); + return(0); +} + +uint32_t komodo_heightstamp(int32_t height) +{ + CBlockIndex *ptr; + if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) + return(ptr->nTime); + //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height); + return(0); +} + +/*void komodo_pindex_init(CBlockIndex *pindex,int32_t height) gets data corrupted +{ + int32_t i,num; uint8_t pubkeys[64][33]; CBlock block; + if ( pindex->didinit != 0 ) + return; + //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->GetHeight(),pindex->notaryid,height); + if ( pindex->didinit == 0 ) + { + pindex->notaryid = -1; + if ( KOMODO_LOADINGBLOCKS == 0 ) + memset(pindex->pubkey33,0xff,33); + else memset(pindex->pubkey33,0,33); + if ( komodo_blockload(block,pindex) == 0 ) + { + komodo_block2pubkey33(pindex->pubkey33,&block); + //for (i=0; i<33; i++) + // fprintf(stderr,"%02x",pindex->pubkey33[i]); + //fprintf(stderr," set pubkey at height %d/%d\n",pindex->GetHeight(),height); + //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 ) + // pindex->didinit = (KOMODO_LOADINGBLOCKS == 0); + } // else fprintf(stderr,"error loading block at %d/%d",pindex->GetHeight(),height); + } + if ( pindex->didinit != 0 && pindex->GetHeight() >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->GetHeight(),(uint32_t)pindex->nTime)) > 0 ) + { + for (i=0; ipubkey33,33) == 0 ) + { + pindex->notaryid = i; + break; + } + } + if ( 0 && i == num ) + { + for (i=0; i<33; i++) + fprintf(stderr,"%02x",pindex->pubkey33[i]); + fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->GetHeight(),height); + } + } +}*/ + +void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) +{ + int32_t num,i; CBlock block; + memset(pubkey33,0,33); + if ( pindex != 0 ) + { + if ( komodo_blockload(block,pindex) == 0 ) + komodo_block2pubkey33(pubkey33,&block); + } +} + +/*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33) +{ + int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33]; + if ( (pindex= chainActive[height]) != 0 ) + { + if ( pindex->didinit != 0 ) + { + if ( destpubkey33 != 0 ) + memcpy(destpubkey33,pindex->pubkey33,33); + return(pindex->notaryid); + } + komodo_index2pubkey33(pubkey33,pindex,height); + if ( destpubkey33 != 0 ) + memcpy(destpubkey33,pindex->pubkey33,33); + if ( pindex->didinit != 0 ) + return(pindex->notaryid); + timestamp = pindex->GetBlockTime(); + if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 ) + { + for (i=0; inTime; + if ( komodo_blockload(block,pindex) == 0 ) + { + komodo_block2pubkey33(pubkeys[i],&block); + for (j=0; j= 0 && i > 0 && mids[i] == mids[0] ) + duplicate++; + } + } + if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) ) + return(1); + else return(0); +} + +int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) +{ + int32_t i,j,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33]; + numnotaries = komodo_notaries(notarypubs33,height,0); + for (i=nonz=0; i= 82000 ) + { + if ( notaryid >= 0 ) + { + for (i=1; i<66; i++) + { + if ( mids[i] == notaryid ) + { + if ( height > 792000 ) + { + 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); + return(-1); + } else break; + } + } + if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 ) + { + if ( height > 807000 ) + return(-2); + } + return(1); + } else return(0); + } + else + { + if ( height >= 34000 && notaryid >= 0 ) + { + if ( height < 79693 ) + limit = 64; + else if ( height < 82000 ) + limit = 8; + else limit = 66; + for (i=1; i 225000 ) + return(-1); + } + } + //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit); + return(1); + } + } + 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) +{ + int32_t depth,notarized_ht; uint256 MoM,kmdtxid; + depth = komodo_MoMdata(¬arized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip); + memset(MoMp,0,sizeof(*MoMp)); + memset(kmdtxidp,0,sizeof(*kmdtxidp)); + *notarized_heightp = 0; + if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) + { + *MoMp = MoM; + *notarized_heightp = notarized_ht; + *kmdtxidp = kmdtxid; + } + return(depth); +} + +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 ) + return(-1); + notarized_height = komodo_notarizeddata(pindex->GetHeight(),¬arized_hash,¬arized_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",ASSETCHAINS_SYMBOL,nHeight,notarized_height); + return(-1); + } + else if ( nHeight == notarized_height && memcmp(&hash,¬arized_hash,sizeof(hash)) != 0 ) + { + fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); + return(-1); + } + } //else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->GetHeight()); + } + //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 ) + // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->GetHeight()); + return(0); +} + +uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) +{ + LOCK(cs_main); + CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; + *txheighttimep = *txheightp = *tiptimep = 0; + *valuep = 0; + if ( !GetTransaction(hash,tx,hashBlock,true) ) + return(0); + uint32_t locktime = 0; + if ( n < tx.vout.size() ) + { + if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) + { + *valuep = tx.vout[n].nValue; + *txheightp = pindex->GetHeight(); + *txheighttimep = pindex->nTime; + if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 0 ) + *tiptimep = (uint32_t)tipindex->nTime; + locktime = tx.nLockTime; + //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); + } + } + 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) +{ + uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; + if ( (pindex= chainActive[tipheight]) != 0 ) + tiptime = (uint32_t)pindex->nTime; + else fprintf(stderr,"cant find height[%d]\n",tipheight); + if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 ) + { + if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) + return(komodo_interest(*txheightp,value,*locktimep,tiptime)); + //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); + 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); + } + return(0); +} + +int32_t komodo_nextheight() +{ + CBlockIndex *pindex; int32_t ht; + if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) + return(ht+1); + else return(komodo_longestchain() + 1); +} + +int32_t komodo_isrealtime(int32_t *kmdheightp) +{ + struct komodo_state *sp; CBlockIndex *pindex; + if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) + *kmdheightp = sp->CURRENT_HEIGHT; + else *kmdheightp = 0; + if ( (pindex= chainActive.LastTip()) != 0 && pindex->GetHeight() >= (int32_t)komodo_longestchain() ) + return(1); + else return(0); +} + +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag) +{ + dispflag = 1; + if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) + { + if ( txheight > 246748 ) + { + if ( txheight < 247205 ) + cmptime -= 16000; + if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME ) + { + if ( tx.nLockTime != 1477258935 && dispflag != 0 ) + { + 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); + } + return(-1); + } + 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); + } + } + return(0); +} + +/* + komodo_checkPOW (fast) is called early in the process and should only refer to data immediately available. it is a filter to prevent bad blocks from going into the local DB. The more blocks we can filter out at this stage, the less junk in the local DB that will just get purged later on. + + komodo_checkPOW (slow) is called right before connecting blocks so all prior blocks can be assumed to be there and all checks must pass + + commission must be in coinbase.vout[1] and must be >= 10000 sats + PoS stake must be without txfee and in the last tx in the block at vout[0] + */ + +CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); + +uint64_t komodo_commission(const CBlock *pblock,int32_t height) +{ + static bool didinit = false,ishush3 = false; + // LABS fungible chains, cannot have any block reward! + if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) + return(0); + + if (!didinit) { + ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; + didinit = true; + } + + int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0; + if ( ASSETCHAINS_FOUNDERS != 0 ) + { + nSubsidy = GetBlockSubsidy(height,Params().GetConsensus()); + //fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION)); + commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN); + + if (ishush3) { + int32_t starting_commission = 125000000, HALVING1 = 340000, INTERVAL = 840000, TRANSITION = 129, BR_END = 5422111; + // 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 + // Transition period of 128 blocks has BR=FR=0 + if (height < TRANSITION) { + commission = 0; + } else if (height < HALVING1) { + commission = starting_commission; + } else if (height < HALVING1+1*INTERVAL) { + commission = starting_commission / 2; + } else if (height < HALVING1+2*INTERVAL) { + commission = starting_commission / 4; + } else if (height < HALVING1+3*INTERVAL) { + commission = starting_commission / 8; + } else if (height < HALVING1+4*INTERVAL) { + commission = starting_commission / 16; + } else if (height < HALVING1+5*INTERVAL) { + commission = starting_commission / 32; + } else if (height < HALVING1+6*INTERVAL) { // Block 5380000 + // Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting + commission = starting_commission / 64; + } else if (height < HALVING1+7*INTERVAL) { + // Block reward will be zero before this is ever reached + commission = starting_commission / 128; // Block 6220000 + } + } + + if ( ASSETCHAINS_FOUNDERS > 1 ) + { + if ( (height % ASSETCHAINS_FOUNDERS) == 0 ) + { + if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) + commission = commission * ASSETCHAINS_FOUNDERS; + else + commission = ASSETCHAINS_FOUNDERS_REWARD; + } + else commission = 0; + } + } + else if ( pblock != 0 ) + { + txn_count = pblock->vtx.size(); + for (i=0; ivtx[i].vout.size(); + for (j=0; j 225000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) + break; + //fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j); + if ( i != 0 || j != 1 ) + total += pblock->vtx[i].vout[j].nValue; + if ( total > 1000000 * COIN ) + { + total = 1000000 * COIN; + break; + } + } + } + commission = ((total / 10000) * ASSETCHAINS_COMMISSION) / 10000; + //commission = ((total * ASSETCHAINS_COMMISSION) / COIN); + } + if ( commission < 10000 ) + commission = 0; + //fprintf(stderr,"-> %.8f\n",(double)commission/COIN); + return(commission); +} + +uint32_t komodo_segid32(char *coinaddr) +{ + bits256 addrhash; + 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) +{ + CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout,newStakerActive; uint256 txid,merkleroot; CScript opret; int8_t segid = -1; + + if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) + { + if (nocache == 0 && pindex->segid >= -1) { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "return cached segid, height." << height << " -> " << (int)pindex->segid << std::endl); // uncommented + return(pindex->segid); + } + if ( komodo_blockload(block,pindex) == 0 ) + { + newStakerActive = komodo_newStakerActive(height, block.nTime); + 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+komodo_hasOpRet(height,pindex->nTime) ) + { + 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); + if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + if ( newStakerActive == 1 && block.vtx[txn_count-1].vout.size() == 2 && DecodeStakingOpRet(block.vtx[txn_count-1].vout[1].scriptPubKey, merkleroot) != 0 ) + newStakerActive++; + if ( newStakerActive == 2 || (newStakerActive == 0 && strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value) ) + { + segid = komodo_segid32(voutaddr) & 0x3f; + //fprintf(stderr, "komodo_segid: ht.%i --> %i\n",height,pindex->segid); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "set calculated segid, height." << height << " -> " << (int)pindex->segid << std::endl); // uncommented + } + } //else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height); + } + } + // The new staker sets segid in komodo_checkPOW, this persists after restart by being saved in the blockindex for blocks past the HF timestamp, to keep backwards compatibility. + // PoW blocks cannot contain a staking tx. If segid has not yet been set, we can set it here accurately. + if ( pindex->segid == -2 ) + pindex->segid = segid; + } + + else + { + // fprintf(stderr, "%s pindex==null ht.%d default value=%d\n", __func__, height, segid); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "pindex==null ht." << height << " segid default value=" << (int)segid << std::endl); + } + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "ht." << height << " return segid=" << (int)segid << std::endl); + return(segid); +} + +void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) +{ + static uint8_t prevhashbuf[100]; static int32_t prevheight; + int32_t i; + if ( height == prevheight && n == 100 ) + memcpy(hashbuf,prevhashbuf,100); + else + { + memset(hashbuf,0xff,n); + for (i=0; i 10 && (tipindex= komodo_chainactive(height - 1)) != 0 ) // disable offchain diffchange + { + diff = (nTime - tipindex->GetMedianTimePast()); + tipdiff = (nTime - tipindex->nTime); + if ( tipdiff > 13*ASSETCHAINS_BLOCKTIME ) + diff = tipdiff; + if ( diff >= 13 * ASSETCHAINS_BLOCKTIME && (height < 30 || tipdiff > 2*ASSETCHAINS_BLOCKTIME) ) + { + mult = diff - 12 * ASSETCHAINS_BLOCKTIME; + mult = (mult / ASSETCHAINS_BLOCKTIME) * ASSETCHAINS_BLOCKTIME + ASSETCHAINS_BLOCKTIME / 2; + origtarget = bnTarget; + bnTarget = bnTarget * arith_uint256(mult * mult); + easy.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); + if ( bnTarget < origtarget || bnTarget > easy ) // deal with overflow + { + bnTarget = easy; + 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); + } //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 newStakerActive) +{ + int32_t oldflag = 0, dispflag = 0 /*set to 1 to debug segids*/; + 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 ( newStakerActive == 0 && height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) ) + return(target); + + sum = arith_uint256(0); + ave = sum; + if ( newStakerActive != 0 ) + { + easydiff.SetCompact(ASSETCHAINS_STAKED_MIN_POW_DIFF,&fNegative,&fOverflow); + if ( height <= 10 ) + return(easydiff); + } + else + easydiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow); + + std::ostringstream strSegids; // for logging segids flags + for (i=n=m=0; i<100; i++) + { + ht = height - 100 + i; + if ( ht <= 1 ) + continue; + if ( (pindex= komodo_chainactive(ht)) != 0 ) + { + if ( komodo_segid(0,ht) >= 0 ) + { + n++; + percPoS++; + if (dispflag != 0 && ASSETCHAINS_STAKED < 100) + strSegids << "0"; // fprintf(stderr,"0"); - not to contaminate 00011100110 output with deeper printing + } + else + { + if (dispflag != 0 && ASSETCHAINS_STAKED < 100) + strSegids << "1"; // fprintf(stderr,"1"); - not to contaminate 00011100110 output with deeper printing + sum += UintToArith256(pindex->GetBlockHash()); + m++; + } + } //else fprintf(stderr, "pindex returned null ht.%i\n",ht); + if (dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9) + strSegids << " " << percPoS << " "; // fprintf(stderr," %d, ", percPoS); + } + if (dispflag != 0 && ASSETCHAINS_STAKED < 100) + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << strSegids.str() << std::endl); + if ( m+n < 100 ) + { + // We do actual PoS % at the start. Requires coin distribution in first 10 blocks! + if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) + percPoS = (percPoS*100) / (m+n); + else + percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; + } + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) + LogPrint(LOG_KOMODOBITCOIND," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); + + *percPoSp = percPoS; + if ( m > 0 ) + { + ave = (sum / arith_uint256(m)); + if ( ave > target ) + ave = target; + } else ave = target; //easydiff; //else return(target); + if ( percPoS == 0 ) + percPoS = 1; + if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget + { + if ( oldflag != 0 ) + 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); + } + else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); + if ( bnTarget > easydiff ) + bnTarget = easydiff; + else if ( bnTarget < ave ) // overflow + { + 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 + if ( newStakerActive != 0 && bnTarget > easydiff ) + bnTarget = easydiff; + 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) +{ + 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,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); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "null value=" << value << " txtime=" << txtime << " blocktime=" << blocktime << " prevtime=" << prevtime << std::endl); + 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); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "segid=" << segid << " address=" << address << std::endl); + for (iter=0; iter<600; iter++) + { + if ( blocktime+iter+segid*2 < txtime+minage ) + continue; + diff = (iter + blocktime - txtime - minage); + // Disable PoS64 on VerusHash, doesnt work properly. + if ( 0 ) // ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) + { + /*if ( PoSperc < ASSETCHAINS_STAKED ) + { + // Under PoS % target and we need to increase diff. + //fprintf(stderr, "PoS too low diff.%i changed to.",diff); + diff = diff * ( (ASSETCHAINS_STAKED - PoSperc + 1) * (ASSETCHAINS_STAKED - PoSperc + 1) * ( nHeight < 50 ? 1000 : 1)); + //fprintf(stderr, "%i \n",diff); + } + else */ + if ( PoSperc > ASSETCHAINS_STAKED ) + { + // Over PoS target need to lower diff. + //fprintf(stderr, "PoS too high diff.%i changed to.",diff); + diff = diff / ( (PoSperc - ASSETCHAINS_STAKED + 1) * (PoSperc - ASSETCHAINS_STAKED + 1) ); + //fprintf(stderr, "%i \n",diff); + } + } + 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 ( 0 ) //&& ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) + { + if ( PoSperc < ASSETCHAINS_STAKED ) + { + // Under PoS % target and we need to increase diff. + //fprintf(stderr, "PoS too low diff.%i changed to.",diff); + if ( blocktime+iter+segid*2 > prevtime+128 ) + coinage *= ((blocktime+iter+segid*2) - (prevtime+102)); + //fprintf(stderr, "%i \n",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]); + 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); */ + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << "block not validated as PoS:" << " hashval=" << hash2str(hashval, 8) << " > bnTarget=" << hash2str(bnTarget, 8) << " iter=" << iter << " winner=" << winner << " segid=" << segid << " coinage=" << coinage << " blocktime-txtime=" << blocktime - txtime << " ht=" << nHeight << " blocktime=" << blocktime << " value=" << value << " diff=" << diff << std::endl); + break; + } + } + //fprintf(stderr,"iterated until iter.%d winner.%d value=%lld segid=%d validateflag=%d\n",iter,winner, value, segid, validateflag); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "iterated until iter=" << iter << " winner=" << winner << " value=" << value << " segid=" << segid << " validateflag=" << validateflag << std::endl); + if ( false && validateflag != 0 ) + { + /*for (int32_t i=31; i>=24; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs "); + for (int32_t 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); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << "hashval=" << hash2str(hashval, 8) << " vs bnTarget=" << hash2str(bnTarget, 8) << "segid=" << segid << " iter=" << iter << " winner=" << winner << " coinage=" << coinage << " blocktime-txtime=" << blocktime - txtime << " ht=" << nHeight << " blocktime=" << blocktime << " value=" << value << " diff=" << diff << std::endl); + } + 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, merkleroot; uint32_t txtime,prevtime=0; int32_t ret,vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; arith_uint256 POWTarget; + if ( ASSETCHAINS_STAKED == 100 && height <= 10 ) + return(1); + BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); + pindex = it != mapBlockIndex.end() ? it->second : NULL; + int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); + // 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,newStakerActive); + } + else + { + // checks opret merkle root and existence of staking tx. + return(komodo_isPoS(pblock,height,0)); + } + txn_count = pblock->vtx.size(); + + // crashes RICK? CCLogPrintF(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, "%s checkblock ht.%d block=%s n.%d vins.%d vouts.%d vout[0].%.8f\n", __func__, height, pblock->GetHash().GetHex().c_str(), 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*/); //uncommented + if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) + { + 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,0) != 0 ) + { + // checks utxo is eligible to stake this block + eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,(char *)"",PoSperc); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << " eligible=" << eligible << " pblock->nTime=" << pblock->nTime << std::endl); + } + else + { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << " komodo_isPoS ht=" << height << " block=" << pblock->GetHash().GetHex() << " returned false" << std::endl); + } + if ( eligible == 0 || eligible > pblock->nTime ) + { + if ( false && ASSETCHAINS_STAKED < 100 ) + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << " PoS failure ht." << height << " eligible." << eligible << " vs blocktime." << pblock->nTime << " lag." << (eligible - pblock->nTime) << " -> check to see if it is PoW block" << std::endl); + } + else + { + isPoS = 1; + /* + If POWTarget is easydiff, then we have no possible way to detect a PoW block from a staking block! + The simplest fix is to make the min diff for PoW blocks higher than the staking mindiff. + The logic here, is that all PoS equihash solutions MUST be under the POW target diff, + The floor diff can be adjusted with ASSETCHAINS_STAKED_MIN_POW_DIFF, this is a hardforking change. + */ + if ( ASSETCHAINS_STAKED < 100 && bhash < POWTarget ) + { + CCLogPrintF(LOG_KOMODOBITCOIND, CCLOG_ERROR, "[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL, height, bhash.GetCompact(), POWTarget.GetCompact()); + isPoS = 0; + } + } + } + } + fprintf(stderr,"%s slow.%d ht.%d isPoS.%d\n", __func__,slowflag,height,isPoS); //uncommented + return(isPoS != 0); +} + +// for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes +bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) +{ + CBlockIndex *pastBlockIndex; + uint256 txid, blkHash; + int32_t txn_count; + uint32_t voutNum; + CAmount value; + bool isPOS = false; + CTxDestination voutaddress, destaddress, cbaddress; + arith_uint256 target, hash; + CTransaction tx; + + if (!pblock->IsVerusPOSBlock()) + { + printf("%s, height %d not POS block\n", pblock->nNonce.GetHex().c_str(), height); + //pblock->nNonce.SetPOSTarget(pblock->nNonce.GetPOSTarget()); + //printf("%s after setting POS target\n", pblock->nNonce.GetHex().c_str()); + return false; + } + + char voutaddr[64], destaddr[64], cbaddr[64]; + + txn_count = pblock->vtx.size(); + + if ( txn_count > 1 ) + { + target.SetCompact(pblock->GetVerusPOSTarget()); + txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; + voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n; + value = pblock->vtx[txn_count-1].vout[0].nValue; + + { + bool validHash = (value != 0); + bool enablePOSNonce = CPOSNonce::NewPOSActive(height); + uint256 rawHash; + arith_uint256 posHash; + + if (validHash && enablePOSNonce) + { + validHash = pblock->GetRawVerusPOSHash(rawHash, height); + posHash = UintToArith256(rawHash) / value; + if (!validHash || posHash > target) + { + validHash = false; + printf("ERROR: invalid nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", + pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); + } + } + if (validHash) + { + if (slowflag == 0) + { + isPOS = true; + } + else if (!(pastBlockIndex = komodo_chainactive(height - 100))) + { + fprintf(stderr,"ERROR: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); + } + else if (!GetTransaction(txid, tx, blkHash, true)) + { + fprintf(stderr,"ERROR: invalid PoS block %s - no source transaction\n",blkHash.ToString().c_str()); + } + else + { + CBlockHeader bh = pastBlockIndex->GetBlockHeader(); + uint256 pastHash = bh.GetVerusEntropyHash(height - 100); + + // if height is over when Nonce is required to be the new format, we check that the new format is correct + // if over when we have the new POS hash function, we validate that as well + // they are 100 blocks apart + CPOSNonce nonce = pblock->nNonce; + + //printf("before nNonce: %s, height: %d\n", pblock->nNonce.GetHex().c_str(), height); + //validHash = pblock->GetRawVerusPOSHash(rawHash, height); + //hash = UintToArith256(rawHash) / tx.vout[voutNum].nValue; + //printf("Raw POShash: %s\n", hash.GetHex().c_str()); + + hash = UintToArith256(tx.GetVerusPOSHash(&nonce, voutNum, height, pastHash)); + + //printf("after nNonce: %s, height: %d\n", nonce.GetHex().c_str(), height); + //printf("POShash: %s\n\n", hash.GetHex().c_str()); + + if (posHash == hash && hash <= target) + { + BlockMap::const_iterator it = mapBlockIndex.find(blkHash); + if ((it == mapBlockIndex.end()) || + !(pastBlockIndex = it->second) || + (height - pastBlockIndex->GetHeight()) < VERUS_MIN_STAKEAGE) + { + fprintf(stderr,"ERROR: invalid PoS block %s - stake source too new or not found\n",blkHash.ToString().c_str()); + } + else + { + // make sure we have the right target + CBlockIndex *previndex; + it = mapBlockIndex.find(pblock->hashPrevBlock); + if (it == mapBlockIndex.end() || !(previndex = it->second)) + { + fprintf(stderr,"ERROR: invalid PoS block %s - no prev block found\n",blkHash.ToString().c_str()); + } + else + { + arith_uint256 cTarget; + uint32_t nBits = lwmaGetNextPOSRequired(previndex, Params().GetConsensus()); + cTarget.SetCompact(nBits); + bool nonceOK = true; + + // check to see how many fail + //if (nonce != pblock->nNonce) + // printf("Mismatched nNonce: %s\nblkHash: %s, height: %d\n", nonce.GetHex().c_str(), pblock->GetHash().GetHex().c_str(), height); + + if (CPOSNonce::NewNonceActive(height) && !nonce.CheckPOSEntropy(pastHash, txid, voutNum)) + { + fprintf(stderr,"ERROR: invalid PoS block %s - nonce entropy corrupted or forged\n",blkHash.ToString().c_str()); + nonceOK = false; + } + else + { + if (cTarget != target) + { + fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); + nonceOK = false; + } + } + if ( nonceOK && ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) && + ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) ) + { + strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); + strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); + if ( !strcmp(destaddr,voutaddr) ) + { + isPOS = true; + CTransaction &cbtx = pblock->vtx[0]; + for (int i = 0; i < cbtx.vout.size(); i++) + { + if (CScriptExt::ExtractVoutDestination(cbtx, i, cbaddress)) + { + strcpy(cbaddr, CBitcoinAddress(cbaddress).ToString().c_str()); + if (!strcmp(destaddr,cbaddr)) + continue; + } + else + { + if (cbtx.vout[i].scriptPubKey.IsOpReturn()) + continue; + isPOS = false; + break; + } + } + } + else + { + fprintf(stderr,"ERROR: invalid PoS block %s - invalid stake or coinbase destination\n",blkHash.ToString().c_str()); + } + } + } + } + } + else + { + printf("ERROR: malformed nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", + pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); + } + } + } + } + } + return(isPOS); +} + +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) +{ + // 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,¬arizedheight,0,1,0,timestamp) != -2 ) + { + fprintf(stderr, "<<<<< &NotarisationNotaries, 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 = komodo_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(NotarisationNotaries.size()+1); + + // Calcualte the amount to pay according to the current era. + AmountToPay = komodo_notarypayamount(height,NotarisationNotaries.size()); + if ( AmountToPay == 0 ) + return(0); + + // 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 < NotarisationNotaries.size(); n++) + { + 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[NotarisationNotaries[n]][i]; + //fprintf(stderr,"%02x",ptr[i+1]); + } + ptr[34] = OP_CHECKSIG; + //fprintf(stderr," set notary %i PUBKEY33 into vout[%i] amount.%lu\n",NotarisationNotaries[n],n+1,AmountToPay); + txNew.vout[n+1].nValue = AmountToPay; + total += txNew.vout[n+1].nValue; + } + return(total); +} + +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries) +{ + uint8_t *script; int32_t scriptlen; + if ( notarypubkeys[0][0] == 0 ) + return false; + BOOST_FOREACH(const CTxIn& txin, vin) + { + uint256 hash; CTransaction tx1; + if ( GetTransaction(txin.prevout.hash,tx1,hash,false) ) + { + for (int8_t i = 0; i < numNN; i++) + { + 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 ) + NotarisationNotaries.push_back(i); + } + } else return false; + } + return true; +} + +uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) +{ + std::vector NotarisationNotaries; uint8_t *script; int32_t scriptlen; + uint64_t timestamp = pblock->nTime; + int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; + numSN = komodo_notaries(notarypubkeys, height, timestamp); + if ( !GetNotarisationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarisationNotaries) ) + return(0); + + // check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems) + std::set checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() ); + if ( checkdupes.size() != NotarisationNotaries.size() ) { + fprintf(stderr, "Possible notarisation is signed multiple times by same notary. It is invalid.\n"); + return(0); + } + const CChainParams& chainparams = Params(); + const Consensus::Params &consensusParams = chainparams.GetConsensus(); + uint64_t totalsats = 0; + 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, NotarisationNotaries, 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"); + return(0); + } + + 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) + { + // skip the coinbase paid to the miner. + if ( n == 0 ) + { + n++; + continue; + } + // Check the pubkeys match the pubkeys in the notarisation. + 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[NotarisationNotaries[n-1]],33) == 0 ) + { + // 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,NotarisationNotaries[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, NotarisationNotaries[n-1]); + } + n++; + } + if ( matches != 0 && matches == NotarisationNotaries.size() && totalsats == total ) + { + //fprintf(stderr, "Validated coinbase matches notarisation in tx position 1.\n" ); + return(totalsats); + } + return(0); +} + +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 + 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 && KOMODO_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(); +} + +int64_t komodo_checkcommission(CBlock *pblock,int32_t 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 ) + { + checktoshis = komodo_commission(pblock,height); + if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 ) + { + //fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN); + return(-1); + } + else if ( checktoshis != 0 ) + { + script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0]; + scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size(); + if ( 0 ) + { + int32_t i; + for (i=0; ivtx[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; + 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; + if ( matched == 0 ) + { + if ( 0 && ASSETCHAINS_SCRIPTPUB.size() > 1 ) + { + int32_t i; + for (i=0; ivtx[0].vout[1].nValue != checktoshis ) + { + fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue)); + return(-1); + } + } + } + return(checktoshis); +} + +bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0; + +int32_t komodo_checkPOW(int64_t stakeTxValue, 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; + if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW == 0 && Params().NetworkIDString() == "regtest" ) + KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; + if ( !CheckEquihashSolution(pblock, Params()) ) + { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "slowflag." << slowflag << " ht." << height << " CheckEquihashSolution failed" << std::endl); + return(-1); + } + hash = pblock->GetHash(); + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "checking block." << hash.GetHex() << " ht." << height << " bits." << pblock->nBits << std::endl); + bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow); + bhash = UintToArith256(hash); + possible = komodo_block2pubkey33(pubkey33,pblock); + if ( height == 0 ) + { + if ( slowflag != 0 ) + { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << "height." << height << " slowflag." << slowflag << " possible."<< possible << " (is bhash > bnTarget)=" << (bhash > bnTarget) << std::endl); + return(0); + } + BlockMap::const_iterator it = mapBlockIndex.find(pblock->hashPrevBlock); + if ( it != mapBlockIndex.end() && (pprev= it->second) != 0 ) + height = pprev->GetHeight() + 1; + if ( height == 0 ) + return(0); + } + //if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) + // bnTarget = komodo_adaptivepow_target(height,bnTarget,pblock->nTime); + if ( ASSETCHAINS_LWMAPOS != 0 && bhash > bnTarget ) + { + // if proof of stake is active, check if this is a valid PoS block before we fail + if (verusCheckPOSBlock(slowflag, pblock, height)) + { + return(0); + } + } + if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget ) + { + failed = 1; + if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case + { + if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 ) + { + for (i=0; i= 2 ) // must PoS or have at least 16x better PoW + { + CBlockIndex *pindex; + BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); + pindex = it != mapBlockIndex.end() ? it->second : NULL; + int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); + if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 ) + { + if ( slowflag == 0 || height <= 100 ) // need all past 100 blocks to calculate PoW target + return(0); + if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64 + return(-1); + else + { + bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED,newStakerActive); + if ( bhash > bnTarget ) + { + LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " bnhash=" << hash2str(bhash, 16) << " > bnTarget=" << hash2str(bnTarget, 16) << " ht." << height << " PoW diff violation PoSperc." << PoSperc << " vs goalperc." << (int)ASSETCHAINS_STAKED << std::endl); + return(-1); + } + else + { + if ( newStakerActive != 0 ) + { + // PoW fake blocks will be rejected here. If a staking tx is included in a block that meets PoW min diff after block 100, then this will reject it. + if ( pblock->vtx.size() > 1 && pblock->vtx[pblock->vtx.size()-1].vout.size() == 2 && DecodeStakingOpRet(pblock->vtx[pblock->vtx.size()-1].vout[1].scriptPubKey, merkleroot) != 0 ) + { + fprintf(stderr, "[%s:%d] staking tx in PoW block, nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL,height,bhash.GetCompact(),bnTarget.GetCompact()); + LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " staking tx found in PoW block, nBits=" << bhash.GetCompact() << " < target=" << bnTarget.GetCompact() << std::endl); + return(-1); + } + // set the pindex->segid as this is now fully validated to be a PoW block. + if ( pindex != 0 ) + { + pindex->segid = -1; + //fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid); + } + } + failed = 0; + } + } + } + else if ( is_PoSblock < 0 ) + { + //fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",ASSETCHAINS_SYMBOL,height,is_PoSblock); + LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " unexpected negative is_PoSblock." << is_PoSblock << std::endl); + return(-1); + } + else + { + if ( slowflag != 0 && newStakerActive != 0 ) + { + int8_t segid = -2; + // the value passed to stakeTxValue, is the blockreward + the valuein-valueout(txfee) of the last tx in the block. + // the coinbase must pay the fees from the last transaction and the block reward at a minimum. + if ( pblock->vtx.size() < 1 || pblock->vtx[0].vout.size() < 1 ) + { + //fprintf(stderr, "[%s:%d] missing coinbase.\n", ASSETCHAINS_SYMBOL, height); + LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " missing coinbase.\n"); + return(-1); + } + else if ( pblock->vtx[0].vout[0].nValue < stakeTxValue ) + { + //fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", ASSETCHAINS_SYMBOL, height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); + LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " coinbase vout0." << (long long)pblock->vtx[0].vout[0].nValue << " < blockreward+stakingtxfee." << (long long)stakeTxValue << std::endl); + return(-1); + } + // set the pindex->segid as this is now fully validated to be a PoS block. + char voutaddr[64]; CTxDestination voutaddress; + if ( ExtractDestination(pblock->vtx.back().vout[0].scriptPubKey,voutaddress) ) + { + strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); + segid = komodo_segid32(voutaddr) & 0x3f; + } + if ( pindex != 0 && segid >= 0 ) + { + pindex->segid = segid; + //fprintf(stderr,"PoS block set segid.%d <- %d\n",height,pindex->segid); + } + } + 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]; + 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); + } + } + 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 ) + { + // 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 ) + { + // Check the notarisation tx is to the crypto address. + if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 ) + { + //fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height); + LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " notarisation is not to crypto address ht." << height << std::endl); + return(-1); + } + // Check min sigs. + int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; + numSN = komodo_notaries(notarypubkeys, height, pblock->nTime); + if ( pblock->vtx[1].vin.size() < numSN/5 ) + { + // fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%lld\n",height,numSN/5,(long long)pblock->vtx[1].vin.size()); + LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " ht." << height << " does not meet minsigs." << numSN / 5 << " sigs." << (long long)pblock->vtx[1].vin.size() << std::endl); + return(-1); + } + } + } + +//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed); + if ( failed != 0 && possible == 0 && notaryid < 0 ) + return(-1); + else return(0); +} + +int32_t komodo_acpublic(uint32_t tiptime) +{ + int32_t acpublic = ASSETCHAINS_PUBLIC; CBlockIndex *pindex; + if ( acpublic == 0 ) + { + if ( tiptime == 0 ) + { + if ( (pindex= chainActive.LastTip()) != 0 ) + tiptime = pindex->nTime; + } + if ( (ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE ) + acpublic = 1; + } + return(acpublic); +} + +int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock) +{ + 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; + n = pblock->vtx.size(); + for (i=0; ivtx[i]; + if ( (m= tx.vin.size()) > 0 ) + { + for (j=0; j= 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 %s\n",dstr(tx.vout[j].nValue),CBitcoinAddress(address).ToString().c_str()); + } + script = (uint8_t *)&tx.vout[j].scriptPubKey[0]; + 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; + } + } + BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) + { + zfunds -= joinsplit.vpub_new; + zfunds += joinsplit.vpub_old; + sproutfunds -= joinsplit.vpub_new; + sproutfunds += joinsplit.vpub_old; + } + zfunds -= tx.valueBalance; + } + *zfundsp = zfunds; + *sproutfundsp = sproutfunds; + if ( ASSETCHAINS_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times + 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)); + return(voutsum - vinsum); +} + +int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) +{ + CBlockIndex *pindex; CBlock block; int64_t zfunds=0,sproutfunds=0,supply = 0; + //fprintf(stderr,"coinsupply %d\n",height); + *zfundsp = *sproutfundsp = 0; + if ( (pindex= komodo_chainactive(height)) != 0 ) + { + while ( pindex != 0 && pindex->GetHeight() > 0 ) + { + if ( pindex->newcoins == 0 && pindex->zfunds == 0 ) + { + if ( komodo_blockload(block,pindex) == 0 ) + pindex->newcoins = komodo_newcoins(&pindex->zfunds,&pindex->sproutfunds,pindex->GetHeight(),&block); + else + { + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "error loading block ht=" << pindex->GetHeight() << std::endl); + return(0); + } + } + supply += pindex->newcoins; + zfunds += pindex->zfunds; + 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)); + pindex = pindex->pprev; + } + } + *zfundsp = zfunds; + *sproutfundsp = sproutfunds; + return(supply); +} + + +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; + struct komodo_staking *newarray = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); + if (newarray == NULL) { + fprintf(stderr, "%s could not allocate memory\n", __func__); + return array; // prevent buf overflow, do not add utxo if no more mem allocated + } + array = newarray; + //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); +} + +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot) +{ + static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; + int32_t PoSperc = 0, newStakerActive; + std::set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; + uint64_t cbPerc = *utxovaluep, tocoinbase = 0; + if (!EnsureWalletIsAvailable(0)) + return 0; + + const bool needSpecialStakeUtxo = false; //conditions of contracts or params for which non-basic utxo for staking are needed + + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + assert(pwalletMain != NULL); + *utxovaluep = 0; + memset(utxotxidp,0,sizeof(*utxotxidp)); + memset(utxovoutp,0,sizeof(*utxovoutp)); + memset(utxosig,0,72); + if ( (tipindex= chainActive.Tip()) == 0 ) + return(0); + nHeight = tipindex->GetHeight() + 1; + if ( (minage= nHeight*3) > 6000 ) // about 100 blocks + minage = 6000; + if ( *blocktimep < tipindex->nTime+60 ) + *blocktimep = tipindex->nTime+60; + komodo_segids(hashbuf,nHeight-101,100); + // this was for VerusHash PoS64 + //tmpTarget = komodo_PoWtarget(&PoSperc,bnTarget,nHeight,ASSETCHAINS_STAKED); + bool resetstaker = false; + if ( array != 0 ) + { + LOCK(cs_main); + CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()]; + CBlock block; CTxDestination addressout; + if (needSpecialStakeUtxo) + resetstaker = true; + else if ( ReadBlockFromDisk(block, pblockindex, 1) && komodo_isPoS(&block, nHeight, &addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) + { + resetstaker = true; + fprintf(stderr, "[%s:%d] Reset ram staker after mining a block!\n",ASSETCHAINS_SYMBOL,nHeight); + } + } + + if ( resetstaker || array == 0 || time(NULL) > lasttime+600 ) + { + LOCK2(cs_main, pwalletMain->cs_wallet); + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + if ( array != 0 ) + { + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; + } + if (!needSpecialStakeUtxo) + { + // add normal staking UTXO: + BOOST_FOREACH(const COutput& out, vecOutputs) + { + if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) + { + fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),counter); + return(0); + } + counter++; + if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) + { + //fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); + continue; + } + CAmount nValue = out.tx->vout[out.i].nValue; + if ( nValue < COIN || !out.fSpendable ) + continue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + if ( ExtractDestination(pk,address) != 0 ) + { + if ( IsMine(*pwalletMain,address) == 0 ) + continue; + if ( myGetTransaction(out.tx->GetHash(),tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) + { + array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); + //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); + } + } + } + } + else + { + struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk; + std::vector > unspentOutputs; + cp = CCinit(&C,EVAL_MARMARA); + mypk = pubkey2pk(Mypubkey()); + Marmarapk = GetUnspendable(cp,0); + GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk); + SetCCunspents(unspentOutputs,coinaddr,true); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + { + txid = it->first.txhash; + vout = (int32_t)it->first.index; + if ( (nValue= it->second.satoshis) < COIN ) + continue; + if ( myGetTransaction(txid,tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) + { + const CScript &scriptPubKey = tx.vout[vout].scriptPubKey; + if ( DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht) != 0 && pk == mypk ) + { + array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey); + } + } + } + } + lasttime = (uint32_t)time(NULL); + } + block_from_future_rejecttime = (uint32_t)GetTime() + ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX; + for (i=winners=0; iGetHeight()+1 > nHeight ) + { + fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),i); + return(0); + } + kp = &array[i]; + eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc); + if ( eligible > 0 ) + { + besttime = 0; + if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc) ) + { + // have elegible utxo to stake with. + if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) + { + // is better than the previous best, so use it instead. + earliest = eligible; + best_scriptPubKey = kp->scriptPubKey; + *utxovaluep = (uint64_t)kp->nValue; + decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); + *utxovoutp = kp->vout; + *txtimep = kp->txtime; + } + /*if ( eligible < block_from_future_rejecttime ) + { + // better to scan all and choose earliest! + fprintf(stderr, "block_from_future_rejecttime.%u vs eligible.%u \n", block_from_future_rejecttime, eligible); + break; + } */ + } + } + } + if ( numkp < 500 && array != 0 ) + { + free(array); + array = 0; + maxkp = numkp = 0; + lasttime = 0; + } + if ( earliest != 0 ) + { + bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid; + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + const CKeyStore& keystore = *pwalletMain; + + // create stake tx + txNew.vin.resize(1); + txNew.vout.resize(1); + txfee = 0; + for (i=0; i<32; i++) + ((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i]; + txNew.vin[0].prevout.hash = revtxid; + txNew.vin[0].prevout.n = *utxovoutp; + txNew.vout[0].scriptPubKey = best_scriptPubKey; + txNew.vout[0].nValue = *utxovaluep - txfee; + txNew.nLockTime = earliest; + txNew.nExpiryHeight = nHeight; + if ( (newStakerActive= komodo_newStakerActive(nHeight,earliest)) != 0 ) + { + if ( cbPerc > 0 && cbPerc <= 100 ) + { + tocoinbase = txNew.vout[0].nValue*cbPerc/100; + txNew.vout[0].nValue -= tocoinbase; + } + txNew.vout.resize(2); + txNew.vout[1].scriptPubKey = EncodeStakingOpRet(merkleroot); + txNew.vout[1].nValue = 0; + } + CTransaction txNewConst(txNew); + { + signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); + UpdateTransaction(txNew, 0, sigdata); + ptr = (uint8_t *)&sigdata.scriptSig[0]; + siglen = sigdata.scriptSig.size(); + for (i = 0; i < siglen; i++) + utxosig[i] = ptr[i]; + *utxovaluep = newStakerActive != 0 ? tocoinbase : txNew.vout[0].nValue+txfee; + } + if (!signSuccess) + LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "failed to create signature\n"); + else + *blocktimep = earliest; + } + return(siglen); +} diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 2e5934cbbc7..d88101a4213 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once // komodo functions that interact with bitcoind C++ #include @@ -22,1291 +22,208 @@ #include "komodo_defs.h" #include "script/standard.h" #include "cc/CCinclude.h" - -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); -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); -unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); -bool EnsureWalletIsAvailable(bool avoidException); -extern bool fRequestShutdown; -extern CScript KOMODO_EARLYTXID_SCRIPTPUB; - -int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew); -uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht); -uint32_t komodo_heightstamp(int32_t height); - -//#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) +#include "komodo_utils.h" // for OS_milliseconds() +#include struct MemoryStruct { char *memory; size_t size; }; 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) - - /************************************************************************ - * * Initialize the string handler so that it is thread safe - * + * @param s the string to initialize ************************************************************************/ +void init_string(return_string *s); -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(); - } - s->ptr[0] = '\0'; -} - -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() ); - } - - 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,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); - } - return nHeight; -} +int tx_height( const uint256 &hash ); +// hash value to string for logging +static std::string hash2str(arith_uint256 hashval, int nbits); /************************************************************************ - * * 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(); - } - memcpy(s->ptr+s->len,ptr,size*nmemb); - s->ptr[new_len] = '\0'; - s->len = new_len; - return(size * nmemb); -} - -/************************************************************************ - * - * return the current system time in milliseconds - * + * @param ptr + * @param size + * @param nmemb + * @param s + * @returns ?? ************************************************************************/ +size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,return_string *s); #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 - * + * @param debugstr + * @param command + * @param rpcstr + * @param params + * @returns ?? ************************************************************************/ - -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; itype&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); -} +char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params); #endif /************************************************************************ - * * perform the query - * + * @param retstrp pointer to return string + * @param debugstr + * @param url + * @param userpass + * @param command + * @param params + * @returns ?? ************************************************************************/ +char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params); + +/**** + * @param ptr + * @param size + * @param nmemb + * @param data + * @returns size * nmemb + */ +static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data); + +/**** + * Do a POST using libcurl + * @param cHandlep curl handle + * @param url the address + * @param userpass + * @param postfields + * @param hdr1 + * @param hdr1 + * @param hdr2 + * @param hdr3 + * @returns the result of the POST + */ +char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); + +/*** + * Make an RPC call to the local daemon + * @param userpass + * @param method + * @param params + * @param port + * @returns results + */ +char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) -{ - static int didinit,count,count2; static double elapsedsum,elapsedsum2; - struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; - char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; - if ( didinit == 0 ) - { - didinit = 1; - curl_global_init(CURL_GLOBAL_ALL); //init the curl session - } - numretries = 0; - if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 ) - specialcase = 1; - else specialcase = 0; - if ( url[0] == 0 ) - strcpy(url,"http://127.0.0.1:7876/nxt"); - if ( specialcase != 0 && 0 ) - printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); -try_again: - if ( retstrp != 0 ) - *retstrp = 0; - starttime = OS_milliseconds(); - curl_handle = curl_easy_init(); - init_string(&s); - headers = curl_slist_append(0,"Expect:"); - - curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); - curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(curl_handle,CURLOPT_URL, url); - curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function - 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 - //curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - //curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 2); - - 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 - } - 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 *)"]"; - } - - databuf = (char *)malloc(256 + strlen(command) + strlen(params)); - sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); - //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf); - // - } //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 ) - { - fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); - free(s.ptr); - return(0); - } - else if ( numretries >= 1 ) - { - fprintf(stderr,"Maximum number of retries exceeded!\n"); - free(s.ptr); - return(0); - } - if ( (rand() % 1000) == 0 ) - printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); - free(s.ptr); - sleep((1< (%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); -} - -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; - mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1)); - 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); -} - -char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3) -{ - struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0; - if ( (cHandle= *cHandlep) == NULL ) - *cHandlep = cHandle = curl_easy_init(); - else curl_easy_reset(cHandle); - //#ifdef DEBUG - //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1); - //#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); - if ( userpass != 0 && userpass[0] != 0 ) - curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass); - if ( postfields != 0 && postfields[0] != 0 ) - { - curl_easy_setopt(cHandle,CURLOPT_POST,1); - curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields); - } - 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); -} - -char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) -{ - //static void *cHandle; - char url[512],*retstr=0,*retstr2=0,postdata[8192]; - if ( params == 0 || params[0] == 0 ) - params = (char *)"[]"; - if ( strlen(params) < sizeof(postdata)-128 ) - { - sprintf(url,(char *)"http://127.0.0.1:%u",port); - sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); - // printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS); - retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); - //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); - } - // fprintf(stderr, "RPC RESP: %s\n", retstr2); - return(retstr2); -} - -int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp) -{ - char *jsonstr,params[256],*userpass; uint16_t port; cJSON *json,*item; int32_t height = 0,txid_height = 0,txid_confirmations = 0; - params[0] = 0; - *kmdnotarized_heightp = 0; - if ( strcmp(dest,"KMD") == 0 ) - { - port = KMD_PORT; - userpass = KMDUSERPASS; - } - else if ( strcmp(dest,"BTC") == 0 ) // this is no longer strictly BTC; depends on -notary= path - { - port = DEST_PORT; - userpass = BTCUSERPASS; - } - else return(0); - if ( userpass[0] != 0 ) - { - if ( strcmp("BTC",dest) != 0 ) - { - if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 ) - { - //printf("(%s)\n",jsonstr); - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (item= jobj(json,(char *)"result")) != 0 ) - { - height = jint(item,(char *)"blocks"); - *kmdnotarized_heightp = height; - } - free_json(json); - } - free(jsonstr); - } - } else { - if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getblockchaininfo",params,port)) != 0 ) - { - //printf("(%s)\n",jsonstr); - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (item= jobj(json,(char *)"result")) != 0 ) - { - height = jint(item,(char *)"blocks"); - *kmdnotarized_heightp = strcmp(dest,"KMD") == 0 ? jint(item,(char *)"notarized") : height; - } - free_json(json); - } - free(jsonstr); - } - } - sprintf(params,"[\"%s\", 1]",txidstr); - if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 ) - { - //printf("(%s)\n",jsonstr); - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (item= jobj(json,(char *)"result")) != 0 ) - { - txid_confirmations = jint(item,(char *)"rawconfirmations"); - if ( txid_confirmations > 0 && height > txid_confirmations ) - txid_height = height - txid_confirmations; - else txid_height = height; - //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height); - } - free_json(json); - } - free(jsonstr); - } - } - return(txid_height); -} - -int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH) -{ - int32_t i; uint256 hash; char params[256]; - for (i=0; i<32; i++) - ((uint8_t *)&hash)[i] = script[2+i]; - if ( hash == NOTARIZED_HASH ) - return(1); - 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",ASSETCHAINS_SYMBOL,height); - return(-1); -} - -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 ) - { - //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> (%s)\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT,jsonstr); - free(jsonstr); - } - //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> NULL\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT); -} - -int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) -{ - char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; - script = _script; - /*params[0] = '['; - params[1] = '"'; - for (i=0; i<32; i++) - sprintf(¶ms[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]); - strcat(params,"\", 1]");*/ - sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str()); - if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) - return(0); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("[%s] src.%s dest.%s params.[%s] ht.%d notarized.%d\n",ASSETCHAINS_SYMBOL,symbol,dest,params,height,NOTARIZED_HEIGHT); - if ( strcmp(dest,"KMD") == 0 ) - { - if ( KMDUSERPASS[0] != 0 ) - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); - //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr); - } - }//else jsonstr = _dex_getrawtransaction(); - else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok - } - else if ( strcmp(dest,"BTC") == 0 ) - { - if ( BTCUSERPASS[0] != 0 ) - { - jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,DEST_PORT); - } - //else jsonstr = _dex_getrawtransaction(); - else return(0); - } - else - { - printf("[%s] verifynotarization error unexpected dest.(%s)\n",ASSETCHAINS_SYMBOL,dest); - return(-1); - } - if ( jsonstr != 0 ) - { - if ( (json= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) > 0 ) - { - vout = jitem(vouts,n-1); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("vout.(%s)\n",jprint(vout,0)); - if ( (skey= jobj(vout,(char *)"scriptPubKey")) != 0 ) - { - if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) - { - //printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str()); - len = strlen(hexstr) >> 1; - decode_hex(script,len,hexstr); - if ( script[1] == 0x4c ) - { - script++; - len--; - } - else if ( script[1] == 0x4d ) - { - script += 2; - len -= 2; - } - retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH); - } - } - } - free_json(txjson); - } - free(jsonstr); - } - return(retval); -} - -CScript komodo_makeopret(CBlock *pblock, bool fNew) -{ - std::vector 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); -} - -/*uint256 komodo_getblockhash(int32_t height) - { - uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32]; - memset(&hash,0,sizeof(hash)); - sprintf(params,"[%d]",height); - if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_RPCPORT)) != 0 ) - { - if ( (result= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (hexstr= jstr(result,(char *)"result")) != 0 ) - { - if ( is_hexstr(hexstr,0) == 64 ) - { - decode_hex(revbuf,32,hexstr); - for (i=0; i<32; i++) - ((uint8_t *)&hash)[i] = revbuf[31-i]; - } - } - free_json(result); - } - printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash); - free(jsonstr); - } - return(hash); - } - - uint256 _komodo_getblockhash(int32_t height);*/ - -uint64_t komodo_seed(int32_t height) -{ - uint64_t seed = 0; - /*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds... - { - uint256 hash,zero; CBlockIndex *pindex; - memset(&hash,0,sizeof(hash)); - memset(&zero,0,sizeof(zero)); - if ( height > 10 ) - height -= 10; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - hash = _komodo_getblockhash(height); - if ( memcmp(&hash,&zero,sizeof(hash)) == 0 ) - hash = komodo_getblockhash(height); - int32_t i; - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" seed.%d\n",height); - seed = arith_uint256(hash.GetHex()).GetLow64(); - } - else*/ - { - seed = (height << 13) ^ (height << 2); - seed <<= 21; - seed |= (height & 0xffffffff); - seed ^= (seed << 17) ^ (seed << 1); - } - return(seed); -} - -uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) -{ - CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts; - *valuep = 0; - if (!GetTransaction(hash, tx, -#ifndef KOMODO_ZCASH - Params().GetConsensus(), -#endif - hashBlock, true)) - { - //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - return(0); - } - numvouts = tx.vout.size(); - //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - if ( n < numvouts ) - { - *valuep = tx.vout[n].nValue; - opret = tx.vout[numvouts-1].scriptPubKey; - if (ExtractDestination(tx.vout[n].scriptPubKey, address)) - strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); - } - return(tx.nLockTime); -} - -CBlockIndex *komodo_getblockindex(uint256 hash) -{ - BlockMap::const_iterator it = mapBlockIndex.find(hash); - return((it != mapBlockIndex.end()) ? it->second : NULL); -} - -uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr) -{ - CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0; - *valuep = 0; - if (!GetTransaction(hash, tx, -#ifndef KOMODO_ZCASH - Params().GetConsensus(), -#endif - hashBlock, true)) - { - //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); - return(0); - } - if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) - 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); -} - -CScript EncodeStakingOpRet(uint256 merkleroot) -{ - CScript opret; uint8_t evalcode = 77; - opret << OP_RETURN << E_MARSHAL(ss << evalcode << merkleroot); - return(opret); -} - -uint8_t DecodeStakingOpRet(CScript scriptPubKey, uint256 &merkleroot) -{ - std::vector vopret; uint8_t evalcode; - GetOpReturnData(scriptPubKey, vopret); - if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> evalcode; ss >> merkleroot) != 0 && evalcode == 77 ) - { - //fprintf(stderr, "evalcode.%i merkleroot.%s\n",evalcode, merkleroot.GetHex().c_str() ); - return(1); - } - return(0); -} - -int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp) -{ - if ( timestamp > nStakedDecemberHardforkTimestamp || komodo_heightstamp(height) > nStakedDecemberHardforkTimestamp ) //December 2019 hardfork - return(1); - else return(0); -} - -int32_t komodo_hasOpRet(int32_t height, uint32_t timestamp) -{ - return((ASSETCHAINS_MARMARA!=0 || komodo_newStakerActive(height, timestamp) == 1)); -} - -bool komodo_checkopret(CBlock *pblock, CScript &merkleroot) -{ - merkleroot = pblock->vtx.back().vout.back().scriptPubKey; - return(merkleroot.IsOpReturn() && merkleroot == komodo_makeopret(pblock, false)); -} - -bool komodo_hardfork_active(uint32_t time) -{ - return ( (ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Height() > nDecemberHardforkHeight) || (ASSETCHAINS_SYMBOL[0] != 0 && time > nStakedDecemberHardforkTimestamp) ); //December 2019 hardfork -} - -bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx); - -uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey) -{ - std::vector vLeaves; - // rereate coinbase tx - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight); - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig = fNew ? (CScript() << nHeight << CScriptNum(1)) + COINBASE_FLAGS : pblock->vtx[0].vin[0].scriptSig; - txNew.vout.resize(1); - txNew.vout[0].scriptPubKey = scriptPubKey; - txNew.vout[0].nValue = 0; - txNew.nExpiryHeight = 0; - txNew.nLockTime = 0; - //fprintf(stderr, "validation: coinbasetx.%s\n", EncodeHexTx(txNew).c_str()); - //fprintf(stderr, "txnew.%s\n", txNew.GetHash().ToString().c_str()); - vLeaves.push_back(txNew.GetHash()); - vLeaves.push_back(prevBlockHash); - for (int32_t i = 1; i < pblock->vtx.size()-(fNew ? 0 : 1); i++) - vLeaves.push_back(pblock->vtx[i].GetHash()); - return GetMerkleRoot(vLeaves); -} - -int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout) -{ - int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid, merkleroot; CScript opret; - if ( ASSETCHAINS_STAKED != 0 ) - { - n = pblock->vtx.size(); - //fprintf(stderr,"ht.%d check for PoS numtx.%d numvins.%d numvouts.%d\n",height,n,(int32_t)pblock->vtx[n-1].vin.size(),(int32_t)pblock->vtx[n-1].vout.size()); - if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) - { - 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) ) - { - if ( addressout != 0 ) *addressout = voutaddress; - strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - //fprintf(stderr,"voutaddr.%s vs destaddr.%s\n",voutaddr,destaddr); - if ( komodo_newStakerActive(height, pblock->nTime) != 0 ) - { - if ( DecodeStakingOpRet(pblock->vtx[n-1].vout[1].scriptPubKey, merkleroot) != 0 && komodo_calcmerkleroot(pblock, pblock->hashPrevBlock, height, false, pblock->vtx[0].vout[0].scriptPubKey) == merkleroot ) - { - return(1); - } - } - else - { - if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 ) - { - if ( ASSETCHAINS_MARMARA == 0 ) - return(1); - else - { - if ( pblock->vtx[n-1].vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= pblock->vtx[n-1].vout.size()) == 2 ) - { - //fprintf(stderr,"validate proper %s %s signature and unlockht preservation\n",voutaddr,destaddr); - return(MarmaraPoScheck(destaddr,opret,pblock->vtx[n-1])); - } - else - { - fprintf(stderr,"reject ht.%d PoS block\n",height); - return(strcmp(ASSETCHAINS_SYMBOL,"MTST2") == 0); // allow until MTST3 - } - } - } - } - } - } - } - return(0); -} - -void komodo_disconnect(CBlockIndex *pindex,CBlock& block) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - //fprintf(stderr,"disconnect ht.%d\n",pindex->GetHeight()); - komodo_init(pindex->GetHeight()); - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - //sp->rewinding = pindex->GetHeight(); - //fprintf(stderr,"-%d ",pindex->GetHeight()); - } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->GetHeight(),ASSETCHAINS_SYMBOL); -} - -int32_t komodo_is_notarytx(const CTransaction& tx) -{ - uint8_t *ptr; static uint8_t crypto777[33]; - if ( tx.vout.size() > 0 ) - { - ptr = (uint8_t *)&tx.vout[0].scriptPubKey[0]; - if ( ptr != 0 ) - { - if ( crypto777[0] == 0 ) - decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); - if ( memcmp(ptr+1,crypto777,33) == 0 ) - { - //printf("found notarytx\n"); - return(1); - } - } - } - return(0); -} - -int32_t komodo_block2height(CBlock *block) -{ - 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 ) - { - height2 = (int32_t)pindex->GetHeight(); - if ( height2 >= 0 ) - return(height2); - } - if ( pindex && block != 0 && block->vtx[0].vin.size() > 0 ) - { - ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0]; - if ( ptr != 0 && block->vtx[0].vin[0].scriptSig.size() > 5 ) - { - //for (i=0; i<6; i++) - // printf("%02x",ptr[i]); - n = ptr[0]; - for (i=0; ivtx[0].vin[0].scriptSig.size(),height); - } - //komodo_init(height); - } - if ( height != height2 ) - { - //fprintf(stderr,"block2height height.%d vs height2.%d, match.%d mismatch.%d\n",height,height2,match,mismatch); - mismatch++; - if ( height2 >= 0 ) - height = height2; - } else match++; - return(height); -} - -int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) -{ - int32_t n; - if ( KOMODO_LOADINGBLOCKS == 0 ) - memset(pubkey33,0xff,33); - else memset(pubkey33,0,33); - if ( block->vtx[0].vout.size() > 0 ) - { - txnouttype whichType; - std::vector> vch = std::vector>(); - if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY) - { - CPubKey pubKey(vch[0]); - if (pubKey.IsValid()) - { - memcpy(pubkey33,vch[0].data(),33); - return true; - } - else memset(pubkey33,0,33); - } - else memset(pubkey33,0,33); - } - return(0); -} - -int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) -{ - 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); -} - -uint32_t komodo_chainactive_timestamp() -{ - if ( chainActive.LastTip() != 0 ) - return((uint32_t)chainActive.LastTip()->GetBlockTime()); - else return(0); -} - -CBlockIndex *komodo_chainactive(int32_t height) -{ - if ( chainActive.LastTip() != 0 ) - { - if ( height <= chainActive.LastTip()->GetHeight() ) - return(chainActive[height]); - // else fprintf(stderr,"komodo_chainactive height %d > active.%d\n",height,chainActive.LastTip()->GetHeight()); - } - //fprintf(stderr,"komodo_chainactive null chainActive.LastTip() height %d\n",height); - return(0); -} - -uint32_t komodo_heightstamp(int32_t height) -{ - CBlockIndex *ptr; - if ( height > 0 && (ptr= komodo_chainactive(height)) != 0 ) - return(ptr->nTime); - //else fprintf(stderr,"komodo_heightstamp null ptr for block.%d\n",height); - return(0); -} - -/*void komodo_pindex_init(CBlockIndex *pindex,int32_t height) gets data corrupted -{ - int32_t i,num; uint8_t pubkeys[64][33]; CBlock block; - if ( pindex->didinit != 0 ) - return; - //printf("pindex.%d komodo_pindex_init notary.%d from height.%d\n",pindex->GetHeight(),pindex->notaryid,height); - if ( pindex->didinit == 0 ) - { - pindex->notaryid = -1; - if ( KOMODO_LOADINGBLOCKS == 0 ) - memset(pindex->pubkey33,0xff,33); - else memset(pindex->pubkey33,0,33); - if ( komodo_blockload(block,pindex) == 0 ) - { - komodo_block2pubkey33(pindex->pubkey33,&block); - //for (i=0; i<33; i++) - // fprintf(stderr,"%02x",pindex->pubkey33[i]); - //fprintf(stderr," set pubkey at height %d/%d\n",pindex->GetHeight(),height); - //if ( pindex->pubkey33[0] == 2 || pindex->pubkey33[0] == 3 ) - // pindex->didinit = (KOMODO_LOADINGBLOCKS == 0); - } // else fprintf(stderr,"error loading block at %d/%d",pindex->GetHeight(),height); - } - if ( pindex->didinit != 0 && pindex->GetHeight() >= 0 && (num= komodo_notaries(pubkeys,(int32_t)pindex->GetHeight(),(uint32_t)pindex->nTime)) > 0 ) - { - for (i=0; ipubkey33,33) == 0 ) - { - pindex->notaryid = i; - break; - } - } - if ( 0 && i == num ) - { - for (i=0; i<33; i++) - fprintf(stderr,"%02x",pindex->pubkey33[i]); - fprintf(stderr," unmatched pubkey at height %d/%d\n",pindex->GetHeight(),height); - } - } -}*/ - -void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) -{ - int32_t num,i; CBlock block; - memset(pubkey33,0,33); - if ( pindex != 0 ) - { - if ( komodo_blockload(block,pindex) == 0 ) - komodo_block2pubkey33(pubkey33,&block); - } -} - -/*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33) -{ - int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33]; - if ( (pindex= chainActive[height]) != 0 ) - { - if ( pindex->didinit != 0 ) - { - if ( destpubkey33 != 0 ) - memcpy(destpubkey33,pindex->pubkey33,33); - return(pindex->notaryid); - } - komodo_index2pubkey33(pubkey33,pindex,height); - if ( destpubkey33 != 0 ) - memcpy(destpubkey33,pindex->pubkey33,33); - if ( pindex->didinit != 0 ) - return(pindex->notaryid); - timestamp = pindex->GetBlockTime(); - if ( (num= komodo_notaries(pubkeys,height,timestamp)) > 0 ) - { - for (i=0; inTime; - if ( komodo_blockload(block,pindex) == 0 ) - { - komodo_block2pubkey33(pubkeys[i],&block); - for (j=0; j= 0 && i > 0 && mids[i] == mids[0] ) - duplicate++; - } - } - if ( i == 66 && duplicate == 0 && (height > 186233 || *nonzpkeysp > 0) ) - return(1); - else return(0); -} - -int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width) -{ - int32_t i,j,nonz,numnotaries; CBlock block; CBlockIndex *pindex; uint8_t notarypubs33[64][33],pubkey33[33]; - numnotaries = komodo_notaries(notarypubs33,height,0); - for (i=nonz=0; i= 82000 ) - { - if ( notaryid >= 0 ) - { - for (i=1; i<66; i++) - { - if ( mids[i] == notaryid ) - { - if ( height > 792000 ) - { - 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); - return(-1); - } else break; - } - } - if ( blocktime != 0 && blocktimes[1] != 0 && blocktime < blocktimes[1]+57 ) - { - if ( height > 807000 ) - return(-2); - } - return(1); - } else return(0); - } - else - { - if ( height >= 34000 && notaryid >= 0 ) - { - if ( height < 79693 ) - limit = 64; - else if ( height < 82000 ) - limit = 8; - else limit = 66; - for (i=1; i 225000 ) - return(-1); - } - } - //fprintf(stderr,"special notaryid.%d ht.%d limit.%d\n",notaryid,height,limit); - return(1); - } - } - 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) -{ - int32_t depth,notarized_ht; uint256 MoM,kmdtxid; - depth = komodo_MoMdata(¬arized_ht,&MoM,&kmdtxid,nHeight,MoMoMp,MoMoMoffsetp,MoMoMdepthp,kmdstartip,kmdendip); - memset(MoMp,0,sizeof(*MoMp)); - memset(kmdtxidp,0,sizeof(*kmdtxidp)); - *notarized_heightp = 0; - if ( depth != 0 && notarized_ht > 0 && nHeight > notarized_ht-depth && nHeight <= notarized_ht ) - { - *MoMp = MoM; - *notarized_heightp = notarized_ht; - *kmdtxidp = kmdtxid; - } - return(depth); -} - -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 ) - return(-1); - notarized_height = komodo_notarizeddata(pindex->GetHeight(),¬arized_hash,¬arized_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",ASSETCHAINS_SYMBOL,nHeight,notarized_height); - return(-1); - } - else if ( nHeight == notarized_height && memcmp(&hash,¬arized_hash,sizeof(hash)) != 0 ) - { - fprintf(stderr,"[%s] nHeight.%d == NOTARIZED_HEIGHT.%d, diff hash\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); - return(-1); - } - } //else fprintf(stderr,"[%s] unexpected error notary_hash %s ht.%d at ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,notary->GetHeight()); - } - //else if ( notarized_height > 0 && notarized_height != 73880 && notarized_height >= 170000 ) - // fprintf(stderr,"[%s] couldnt find notarized.(%s %d) ht.%d\n",ASSETCHAINS_SYMBOL,notarized_hash.ToString().c_str(),notarized_height,pindex->GetHeight()); - return(0); -} - -uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n) -{ - LOCK(cs_main); - CTransaction tx; uint256 hashBlock; CBlockIndex *pindex,*tipindex; - *txheighttimep = *txheightp = *tiptimep = 0; - *valuep = 0; - if ( !GetTransaction(hash,tx,hashBlock,true) ) - return(0); - uint32_t locktime = 0; - if ( n < tx.vout.size() ) - { - if ( (pindex= komodo_getblockindex(hashBlock)) != 0 ) - { - *valuep = tx.vout[n].nValue; - *txheightp = pindex->GetHeight(); - *txheighttimep = pindex->nTime; - if ( *tiptimep == 0 && (tipindex= chainActive.LastTip()) != 0 ) - *tiptimep = (uint32_t)tipindex->nTime; - locktime = tx.nLockTime; - //fprintf(stderr,"tx locktime.%u %.8f height.%d | tiptime.%u\n",locktime,(double)*valuep/COIN,*txheightp,*tiptimep); - } - } - 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) -{ - uint64_t value; uint32_t tiptime=0,txheighttimep; CBlockIndex *pindex; - if ( (pindex= chainActive[tipheight]) != 0 ) - tiptime = (uint32_t)pindex->nTime; - else fprintf(stderr,"cant find height[%d]\n",tipheight); - if ( (*locktimep= komodo_interest_args(&txheighttimep,txheightp,&tiptime,&value,hash,n)) != 0 ) - { - if ( (checkvalue == 0 || value == checkvalue) && (checkheight == 0 || *txheightp == checkheight) ) - return(komodo_interest(*txheightp,value,*locktimep,tiptime)); - //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); - 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); - } - return(0); -} - -int32_t komodo_nextheight() -{ - CBlockIndex *pindex; int32_t ht; - if ( (pindex= chainActive.LastTip()) != 0 && (ht= pindex->GetHeight()) > 0 ) - return(ht+1); - else return(komodo_longestchain() + 1); -} - -int32_t komodo_isrealtime(int32_t *kmdheightp) -{ - struct komodo_state *sp; CBlockIndex *pindex; - if ( (sp= komodo_stateptrget((char *)"KMD")) != 0 ) - *kmdheightp = sp->CURRENT_HEIGHT; - else *kmdheightp = 0; - if ( (pindex= chainActive.LastTip()) != 0 && pindex->GetHeight() >= (int32_t)komodo_longestchain() ) - return(1); - else return(0); -} - -int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag) -{ - dispflag = 1; - if ( KOMODO_REWIND == 0 && ASSETCHAINS_SYMBOL[0] == 0 && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD ) //1473793441 ) - { - if ( txheight > 246748 ) - { - if ( txheight < 247205 ) - cmptime -= 16000; - if ( (int64_t)tx.nLockTime < cmptime-KOMODO_MAXMEMPOOLTIME ) - { - if ( tx.nLockTime != 1477258935 && dispflag != 0 ) - { - 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); - } - return(-1); - } - 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); - } - } - return(0); -} +/**** + * @param dest the currency + * @param txidstr the txid desired + * @param kmdnotarized_heightp will be set to the KMD notarized height + * @returns txid height + */ +int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); + +int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 notarized_hash); + +void komodo_reconsiderblock(uint256 blockhash); + +int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 notarized_hash,uint256 notarized_desttxid); + +CScript komodo_makeopret(CBlock *pblock, bool fNew); + +/*** + * Get seed + * @param height + * @returns seed for specified height + */ +uint64_t komodo_seed(int32_t height); + +/***** + * Get previous staking utxo opret, address and txtime + * @param opret + * @param valuep + * @param hash + * @param n + * @param destaddr + * @returns tx lock time + */ +uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr); + +/*** + * Get the block index + * @param hash + * @returns the block index for the specified hash + */ +CBlockIndex *komodo_getblockindex(uint256 hash); + +/***** + * Extension point to add preferences for stakes (dimxy) + * TODO: what if for some chain several chain's params require different multipliers. Which to select, max? + * @param tx + * @param nvout + * @returns multiplier + */ +static int32_t GetStakeMultiplier(CTransaction &tx, int32_t nvout); + + +uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr); + +CScript EncodeStakingOpRet(uint256 merkleroot); + +uint8_t DecodeStakingOpRet(CScript scriptPubKey, uint256 &merkleroot); + +int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); + +int32_t komodo_hasOpRet(int32_t height, uint32_t timestamp); + +bool komodo_checkopret(CBlock *pblock, CScript &merkleroot); + +bool komodo_hardfork_active(uint32_t time); + +uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); + +// checks if block is PoS: +// last tx should point to the previous staking utxo (that is spent to self) +// returns 1 if this is PoS block and 0 if false +int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout); + +void komodo_disconnect(CBlockIndex *pindex,CBlock& block); + +int32_t komodo_is_notarytx(const CTransaction& tx); + +int32_t komodo_block2height(CBlock *block); + +int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block); + +int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex); + +uint32_t komodo_chainactive_timestamp(); + +CBlockIndex *komodo_chainactive(int32_t height); + +uint32_t komodo_heightstamp(int32_t height); + +void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); + +int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t blocktimes[66],int32_t *nonzpkeysp,int32_t height); + +int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); + +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); + +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); + +CBlockIndex *komodo_blockindex(uint256 hash); + +int32_t komodo_blockheight(uint256 hash); + +uint32_t komodo_blocktime(uint256 hash); + +int32_t komodo_checkpoint(int32_t *notarized_heightp,int32_t nHeight,uint256 hash); + +uint32_t komodo_interest_args(uint32_t *txheighttimep,int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n); + +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); + +int32_t komodo_nextheight(); + +int32_t komodo_isrealtime(int32_t *kmdheightp); + +int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t cmptime,int32_t dispflag); /* 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. @@ -1317,1552 +234,53 @@ int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_ PoS stake must be without txfee and in the last tx in the block at vout[0] */ -CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); - -uint64_t komodo_commission(const CBlock *pblock,int32_t height) -{ - static bool didinit = false,ishush3 = false; - // LABS fungible chains, cannot have any block reward! - if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) - return(0); - - if (!didinit) { - ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; - didinit = true; - } - - int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0; - if ( ASSETCHAINS_FOUNDERS != 0 ) - { - nSubsidy = GetBlockSubsidy(height,Params().GetConsensus()); - //fprintf(stderr,"ht.%d nSubsidy %.8f prod %llu\n",height,(double)nSubsidy/COIN,(long long)(nSubsidy * ASSETCHAINS_COMMISSION)); - commission = ((nSubsidy * ASSETCHAINS_COMMISSION) / COIN); - - if (ishush3) { - int32_t starting_commission = 125000000, HALVING1 = 340000, INTERVAL = 840000, TRANSITION = 129, BR_END = 5422111; - // 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 - // Transition period of 128 blocks has BR=FR=0 - if (height < TRANSITION) { - commission = 0; - } else if (height < HALVING1) { - commission = starting_commission; - } else if (height < HALVING1+1*INTERVAL) { - commission = starting_commission / 2; - } else if (height < HALVING1+2*INTERVAL) { - commission = starting_commission / 4; - } else if (height < HALVING1+3*INTERVAL) { - commission = starting_commission / 8; - } else if (height < HALVING1+4*INTERVAL) { - commission = starting_commission / 16; - } else if (height < HALVING1+5*INTERVAL) { - commission = starting_commission / 32; - } else if (height < HALVING1+6*INTERVAL) { // Block 5380000 - // Block reward will go to zero between 7th+8th halvings, ac_end may need adjusting - commission = starting_commission / 64; - } else if (height < HALVING1+7*INTERVAL) { - // Block reward will be zero before this is ever reached - commission = starting_commission / 128; // Block 6220000 - } - } - - if ( ASSETCHAINS_FOUNDERS > 1 ) - { - if ( (height % ASSETCHAINS_FOUNDERS) == 0 ) - { - if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) - commission = commission * ASSETCHAINS_FOUNDERS; - else - commission = ASSETCHAINS_FOUNDERS_REWARD; - } - else commission = 0; - } - } - else if ( pblock != 0 ) - { - txn_count = pblock->vtx.size(); - for (i=0; ivtx[i].vout.size(); - for (j=0; j 225000 && ASSETCHAINS_STAKED != 0 && txn_count > 1 && i == txn_count-1 && j == n-1 ) - break; - //fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[i].vout[j].nValue),j); - if ( i != 0 || j != 1 ) - total += pblock->vtx[i].vout[j].nValue; - if ( total > 1000000 * COIN ) - { - total = 1000000 * COIN; - break; - } - } - } - commission = ((total / 10000) * ASSETCHAINS_COMMISSION) / 10000; - //commission = ((total * ASSETCHAINS_COMMISSION) / COIN); - } - if ( commission < 10000 ) - commission = 0; - //fprintf(stderr,"-> %.8f\n",(double)commission/COIN); - return(commission); -} - -uint32_t komodo_segid32(char *coinaddr) -{ - bits256 addrhash; - 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) -{ - CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout,newStakerActive; uint256 txid,merkleroot; CScript opret; int8_t segid = -1; - if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) - { - if ( nocache == 0 && pindex->segid >= -1 ) - return(pindex->segid); - if ( komodo_blockload(block,pindex) == 0 ) - { - newStakerActive = komodo_newStakerActive(height, block.nTime); - 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+komodo_hasOpRet(height,pindex->nTime) ) - { - 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); - if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) - { - strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - if ( newStakerActive == 1 && block.vtx[txn_count-1].vout.size() == 2 && DecodeStakingOpRet(block.vtx[txn_count-1].vout[1].scriptPubKey, merkleroot) != 0 ) - newStakerActive++; - if ( newStakerActive == 2 || (newStakerActive == 0 && strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value) ) - { - segid = komodo_segid32(voutaddr) & 0x3f; - //fprintf(stderr, "komodo_segid: ht.%i --> %i\n",height,pindex->segid); - } - } //else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height); - } - } - // The new staker sets segid in komodo_checkPOW, this persists after restart by being saved in the blockindex for blocks past the HF timestamp, to keep backwards compatibility. - // PoW blocks cannot contain a staking tx. If segid has not yet been set, we can set it here accurately. - if ( pindex->segid == -2 ) - pindex->segid = segid; - } - return(segid); -} - -void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n) -{ - static uint8_t prevhashbuf[100]; static int32_t prevheight; - int32_t i; - if ( height == prevheight && n == 100 ) - memcpy(hashbuf,prevhashbuf,100); - else - { - memset(hashbuf,0xff,n); - for (i=0; i 10 && (tipindex= komodo_chainactive(height - 1)) != 0 ) // disable offchain diffchange - { - diff = (nTime - tipindex->GetMedianTimePast()); - tipdiff = (nTime - tipindex->nTime); - if ( tipdiff > 13*ASSETCHAINS_BLOCKTIME ) - diff = tipdiff; - if ( diff >= 13 * ASSETCHAINS_BLOCKTIME && (height < 30 || tipdiff > 2*ASSETCHAINS_BLOCKTIME) ) - { - mult = diff - 12 * ASSETCHAINS_BLOCKTIME; - mult = (mult / ASSETCHAINS_BLOCKTIME) * ASSETCHAINS_BLOCKTIME + ASSETCHAINS_BLOCKTIME / 2; - origtarget = bnTarget; - bnTarget = bnTarget * arith_uint256(mult * mult); - easy.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); - if ( bnTarget < origtarget || bnTarget > easy ) // deal with overflow - { - bnTarget = easy; - 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); - } //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 newStakerActive) -{ - int32_t oldflag = 0,dispflag = 0; - 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 ( newStakerActive == 0 && height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) ) - return(target); - - sum = arith_uint256(0); - ave = sum; - if ( newStakerActive != 0 ) - { - easydiff.SetCompact(ASSETCHAINS_STAKED_MIN_POW_DIFF,&fNegative,&fOverflow); - if ( height <= 10 ) - return(easydiff); - } - else - easydiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow); - for (i=n=m=0; i<100; i++) - { - ht = height - 100 + i; - if ( ht <= 1 ) - continue; - if ( (pindex= komodo_chainactive(ht)) != 0 ) - { - if ( komodo_segid(0,ht) >= 0 ) - { - n++; - percPoS++; - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - fprintf(stderr,"0"); - } - else - { - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - fprintf(stderr,"1"); - sum += UintToArith256(pindex->GetBlockHash()); - m++; - } - } //else fprintf(stderr, "pindex returned null ht.%i\n",ht); - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) - fprintf(stderr," %d, ",percPoS); - } - if ( m+n < 100 ) - { - // We do actual PoS % at the start. Requires coin distribution in first 10 blocks! - if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) - percPoS = (percPoS*100) / (m+n); - else - percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; - } - if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); - *percPoSp = percPoS; - if ( m > 0 ) - { - ave = (sum / arith_uint256(m)); - if ( ave > target ) - ave = target; - } else ave = target; //easydiff; //else return(target); - if ( percPoS == 0 ) - percPoS = 1; - if ( percPoS < goalperc ) // increase PoW diff -> lower bnTarget - { - if ( oldflag != 0 ) - 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); - } - else bnTarget = (ave / arith_uint256(goalperc * goalperc)) * arith_uint256(percPoS * percPoS * percPoS); - if ( bnTarget > easydiff ) - bnTarget = easydiff; - else if ( bnTarget < ave ) // overflow - { - 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 - if ( newStakerActive != 0 && bnTarget > easydiff ) - bnTarget = easydiff; - 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) -{ - 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); - // Disable PoS64 on VerusHash, doesnt work properly. - if ( 0 ) // ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) - { - /*if ( PoSperc < ASSETCHAINS_STAKED ) - { - // Under PoS % target and we need to increase diff. - //fprintf(stderr, "PoS too low diff.%i changed to.",diff); - diff = diff * ( (ASSETCHAINS_STAKED - PoSperc + 1) * (ASSETCHAINS_STAKED - PoSperc + 1) * ( nHeight < 50 ? 1000 : 1)); - //fprintf(stderr, "%i \n",diff); - } - else */ - if ( PoSperc > ASSETCHAINS_STAKED ) - { - // Over PoS target need to lower diff. - //fprintf(stderr, "PoS too high diff.%i changed to.",diff); - diff = diff / ( (PoSperc - ASSETCHAINS_STAKED + 1) * (PoSperc - ASSETCHAINS_STAKED + 1) ); - //fprintf(stderr, "%i \n",diff); - } - } - 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 ( 0 ) //&& ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 ) - { - if ( PoSperc < ASSETCHAINS_STAKED ) - { - // Under PoS % target and we need to increase diff. - //fprintf(stderr, "PoS too low diff.%i changed to.",diff); - if ( blocktime+iter+segid*2 > prevtime+128 ) - coinage *= ((blocktime+iter+segid*2) - (prevtime+102)); - //fprintf(stderr, "%i \n",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]); - 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, merkleroot; uint32_t txtime,prevtime=0; int32_t ret,vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; arith_uint256 POWTarget; - if ( ASSETCHAINS_STAKED == 100 && height <= 10 ) - return(1); - BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); - pindex = it != mapBlockIndex.end() ? it->second : NULL; - int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); - // 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,newStakerActive); - } - else - { - // checks opret merkle root and existence of staking tx. - return(komodo_isPoS(pblock,height,0)); - } - txn_count = pblock->vtx.size(); - //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); - if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) - { - 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,0) != 0 ) - { - // checks utxo is eligible to stake this block - eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,(char *)"",PoSperc); - } - 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)); - } - else - { - isPoS = 1; - /* - If POWTarget is easydiff, then we have no possible way to detect a PoW block from a staking block! - The simplest fix is to make the min diff for PoW blocks higher than the staking mindiff. - The logic here, is that all PoS equihash solutions MUST be under the POW target diff, - The floor diff can be adjusted with ASSETCHAINS_STAKED_MIN_POW_DIFF, this is a hardforking change. - */ - if ( ASSETCHAINS_STAKED < 100 && bhash < POWTarget ) - { - fprintf(stderr,"[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL, height, bhash.GetCompact(), POWTarget.GetCompact()); - isPoS = 0; - } - } - } - } - //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_commission(const CBlock *pblock,int32_t height); + +uint32_t komodo_segid32(char *coinaddr); + +int8_t komodo_segid(int32_t nocache,int32_t height); + +void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n); + +uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout); + +arith_uint256 komodo_adaptivepow_target(int32_t height,arith_uint256 bnTarget,uint32_t nTime); + +arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive); + +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); + +int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget,arith_uint256 bhash); // for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes -bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) -{ - CBlockIndex *pastBlockIndex; - uint256 txid, blkHash; - int32_t txn_count; - uint32_t voutNum; - CAmount value; - bool isPOS = false; - CTxDestination voutaddress, destaddress, cbaddress; - arith_uint256 target, hash; - CTransaction tx; - - if (!pblock->IsVerusPOSBlock()) - { - printf("%s, height %d not POS block\n", pblock->nNonce.GetHex().c_str(), height); - //pblock->nNonce.SetPOSTarget(pblock->nNonce.GetPOSTarget()); - //printf("%s after setting POS target\n", pblock->nNonce.GetHex().c_str()); - return false; - } - - char voutaddr[64], destaddr[64], cbaddr[64]; - - txn_count = pblock->vtx.size(); - - if ( txn_count > 1 ) - { - target.SetCompact(pblock->GetVerusPOSTarget()); - txid = pblock->vtx[txn_count-1].vin[0].prevout.hash; - voutNum = pblock->vtx[txn_count-1].vin[0].prevout.n; - value = pblock->vtx[txn_count-1].vout[0].nValue; - - { - bool validHash = (value != 0); - bool enablePOSNonce = CPOSNonce::NewPOSActive(height); - uint256 rawHash; - arith_uint256 posHash; - - if (validHash && enablePOSNonce) - { - validHash = pblock->GetRawVerusPOSHash(rawHash, height); - posHash = UintToArith256(rawHash) / value; - if (!validHash || posHash > target) - { - validHash = false; - printf("ERROR: invalid nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", - pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); - } - } - if (validHash) - { - if (slowflag == 0) - { - isPOS = true; - } - else if (!(pastBlockIndex = komodo_chainactive(height - 100))) - { - fprintf(stderr,"ERROR: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); - } - else -#ifndef KOMODO_ZCASH - if (!GetTransaction(txid, tx, Params().GetConsensus(), blkHash, true)) -#else - if (!GetTransaction(txid, tx, blkHash, true)) -#endif - { - fprintf(stderr,"ERROR: invalid PoS block %s - no source transaction\n",blkHash.ToString().c_str()); - } - else - { - CBlockHeader bh = pastBlockIndex->GetBlockHeader(); - uint256 pastHash = bh.GetVerusEntropyHash(height - 100); - - // if height is over when Nonce is required to be the new format, we check that the new format is correct - // if over when we have the new POS hash function, we validate that as well - // they are 100 blocks apart - CPOSNonce nonce = pblock->nNonce; - - //printf("before nNonce: %s, height: %d\n", pblock->nNonce.GetHex().c_str(), height); - //validHash = pblock->GetRawVerusPOSHash(rawHash, height); - //hash = UintToArith256(rawHash) / tx.vout[voutNum].nValue; - //printf("Raw POShash: %s\n", hash.GetHex().c_str()); - - hash = UintToArith256(tx.GetVerusPOSHash(&nonce, voutNum, height, pastHash)); - - //printf("after nNonce: %s, height: %d\n", nonce.GetHex().c_str(), height); - //printf("POShash: %s\n\n", hash.GetHex().c_str()); - - if (posHash == hash && hash <= target) - { - BlockMap::const_iterator it = mapBlockIndex.find(blkHash); - if ((it == mapBlockIndex.end()) || - !(pastBlockIndex = it->second) || - (height - pastBlockIndex->GetHeight()) < VERUS_MIN_STAKEAGE) - { - fprintf(stderr,"ERROR: invalid PoS block %s - stake source too new or not found\n",blkHash.ToString().c_str()); - } - else - { - // make sure we have the right target - CBlockIndex *previndex; - it = mapBlockIndex.find(pblock->hashPrevBlock); - if (it == mapBlockIndex.end() || !(previndex = it->second)) - { - fprintf(stderr,"ERROR: invalid PoS block %s - no prev block found\n",blkHash.ToString().c_str()); - } - else - { - arith_uint256 cTarget; - uint32_t nBits = lwmaGetNextPOSRequired(previndex, Params().GetConsensus()); - cTarget.SetCompact(nBits); - bool nonceOK = true; - - // check to see how many fail - //if (nonce != pblock->nNonce) - // printf("Mismatched nNonce: %s\nblkHash: %s, height: %d\n", nonce.GetHex().c_str(), pblock->GetHash().GetHex().c_str(), height); - - if (CPOSNonce::NewNonceActive(height) && !nonce.CheckPOSEntropy(pastHash, txid, voutNum)) - { - fprintf(stderr,"ERROR: invalid PoS block %s - nonce entropy corrupted or forged\n",blkHash.ToString().c_str()); - nonceOK = false; - } - else - { - if (cTarget != target) - { - fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); - nonceOK = false; - } - } - if ( nonceOK && ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey, voutaddress) && - ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) ) - { - strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); - strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); - if ( !strcmp(destaddr,voutaddr) ) - { - isPOS = true; - CTransaction &cbtx = pblock->vtx[0]; - for (int i = 0; i < cbtx.vout.size(); i++) - { - if (CScriptExt::ExtractVoutDestination(cbtx, i, cbaddress)) - { - strcpy(cbaddr, CBitcoinAddress(cbaddress).ToString().c_str()); - if (!strcmp(destaddr,cbaddr)) - continue; - } - else - { - if (cbtx.vout[i].scriptPubKey.IsOpReturn()) - continue; - isPOS = false; - break; - } - } - } - else - { - fprintf(stderr,"ERROR: invalid PoS block %s - invalid stake or coinbase destination\n",blkHash.ToString().c_str()); - } - } - } - } - } - else - { - printf("ERROR: malformed nonce value for PoS block\nnNonce: %s\nrawHash: %s\nposHash: %s\nvalue: %lu\n", - pblock->nNonce.GetHex().c_str(), rawHash.GetHex().c_str(), posHash.GetHex().c_str(), value); - } - } - } - } - } - return(isPOS); -} - -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) -{ - // 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,¬arizedheight,0,1,0,timestamp) != -2 ) - { - fprintf(stderr, "<<<<< &NotarisationNotaries, 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 = komodo_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(NotarisationNotaries.size()+1); - - // Calcualte the amount to pay according to the current era. - AmountToPay = komodo_notarypayamount(height,NotarisationNotaries.size()); - if ( AmountToPay == 0 ) - return(0); - - // 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 < NotarisationNotaries.size(); n++) - { - 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[NotarisationNotaries[n]][i]; - //fprintf(stderr,"%02x",ptr[i+1]); - } - ptr[34] = OP_CHECKSIG; - //fprintf(stderr," set notary %i PUBKEY33 into vout[%i] amount.%lu\n",NotarisationNotaries[n],n+1,AmountToPay); - txNew.vout[n+1].nValue = AmountToPay; - total += txNew.vout[n+1].nValue; - } - return(total); -} - -bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries) -{ - uint8_t *script; int32_t scriptlen; - if ( notarypubkeys[0][0] == 0 ) - return false; - BOOST_FOREACH(const CTxIn& txin, vin) - { - uint256 hash; CTransaction tx1; - if ( GetTransaction(txin.prevout.hash,tx1,hash,false) ) - { - for (int8_t i = 0; i < numNN; i++) - { - 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 ) - NotarisationNotaries.push_back(i); - } - } else return false; - } - return true; -} - -uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) -{ - std::vector NotarisationNotaries; uint8_t *script; int32_t scriptlen; - uint64_t timestamp = pblock->nTime; - int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; - numSN = komodo_notaries(notarypubkeys, height, timestamp); - if ( !GetNotarisationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarisationNotaries) ) - return(0); - - // check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems) - std::set checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() ); - if ( checkdupes.size() != NotarisationNotaries.size() ) { - fprintf(stderr, "Possible notarisation is signed multiple times by same notary. It is invalid.\n"); - return(0); - } - const CChainParams& chainparams = Params(); - const Consensus::Params &consensusParams = chainparams.GetConsensus(); - uint64_t totalsats = 0; - 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, NotarisationNotaries, 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"); - return(0); - } - - 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) - { - // skip the coinbase paid to the miner. - if ( n == 0 ) - { - n++; - continue; - } - // Check the pubkeys match the pubkeys in the notarisation. - 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[NotarisationNotaries[n-1]],33) == 0 ) - { - // 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,NotarisationNotaries[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, NotarisationNotaries[n-1]); - } - n++; - } - if ( matches != 0 && matches == NotarisationNotaries.size() && totalsats == total ) - { - //fprintf(stderr, "Validated coinbase matches notarisation in tx position 1.\n" ); - return(totalsats); - } - return(0); -} - -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 - 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 && KOMODO_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(); -} - -int64_t komodo_checkcommission(CBlock *pblock,int32_t 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 ) - { - checktoshis = komodo_commission(pblock,height); - if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 ) - { - //fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN); - return(-1); - } - else if ( checktoshis != 0 ) - { - script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0]; - scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size(); - if ( 0 ) - { - int32_t i; - for (i=0; ivtx[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; - 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; - if ( matched == 0 ) - { - if ( 0 && ASSETCHAINS_SCRIPTPUB.size() > 1 ) - { - int32_t i; - for (i=0; ivtx[0].vout[1].nValue != checktoshis ) - { - fprintf(stderr,"ht.%d checktoshis %.8f vs actual vout[1] %.8f\n",height,dstr(checktoshis),dstr(pblock->vtx[0].vout[1].nValue)); - return(-1); - } - } - } - return(checktoshis); -} - -bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0; - -int32_t komodo_checkPOW(int64_t stakeTxValue, 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; - 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); - } - hash = pblock->GetHash(); - bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow); - bhash = UintToArith256(hash); - possible = komodo_block2pubkey33(pubkey33,pblock); - if ( height == 0 ) - { - if ( slowflag != 0 ) - { - fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget); - return(0); - } - BlockMap::const_iterator it = mapBlockIndex.find(pblock->hashPrevBlock); - if ( it != mapBlockIndex.end() && (pprev= it->second) != 0 ) - height = pprev->GetHeight() + 1; - if ( height == 0 ) - return(0); - } - //if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) - // bnTarget = komodo_adaptivepow_target(height,bnTarget,pblock->nTime); - if ( ASSETCHAINS_LWMAPOS != 0 && bhash > bnTarget ) - { - // if proof of stake is active, check if this is a valid PoS block before we fail - if (verusCheckPOSBlock(slowflag, pblock, height)) - { - return(0); - } - } - if ( (ASSETCHAINS_SYMBOL[0] != 0 || height > 792000) && bhash > bnTarget ) - { - failed = 1; - if ( height > 0 && ASSETCHAINS_SYMBOL[0] == 0 ) // for the fast case - { - if ( (n= komodo_notaries(pubkeys,height,pblock->nTime)) > 0 ) - { - for (i=0; i= 2 ) // must PoS or have at least 16x better PoW - { - CBlockIndex *pindex; - BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash()); - pindex = it != mapBlockIndex.end() ? it->second : NULL; - int32_t newStakerActive = komodo_newStakerActive(height, pblock->nTime); - if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 ) - { - if ( slowflag == 0 || height <= 100 ) // need all past 100 blocks to calculate PoW target - return(0); - if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64 - return(-1); - else - { - bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED,newStakerActive); - if ( bhash > bnTarget ) - { - for (i=31; i>=16; i--) - 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 - { - if ( newStakerActive != 0 ) - { - // PoW fake blocks will be rejected here. If a staking tx is included in a block that meets PoW min diff after block 100, then this will reject it. - if ( pblock->vtx.size() > 1 && pblock->vtx[pblock->vtx.size()-1].vout.size() == 2 && DecodeStakingOpRet(pblock->vtx[pblock->vtx.size()-1].vout[1].scriptPubKey, merkleroot) != 0 ) - { - fprintf(stderr, "[%s:%d] staking tx in PoW block, nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL,height,bhash.GetCompact(),bnTarget.GetCompact()); - return(-1); - } - // set the pindex->segid as this is now fully validated to be a PoW block. - if ( pindex != 0 ) - { - pindex->segid = -1; - //fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid); - } - } - failed = 0; - } - } - } - else if ( is_PoSblock < 0 ) - { - fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",ASSETCHAINS_SYMBOL,height,is_PoSblock); - return(-1); - } - else - { - if ( slowflag != 0 && newStakerActive != 0 ) - { - int8_t segid = -2; - // the value passed to stakeTxValue, is the blockreward + the valuein-valueout(txfee) of the last tx in the block. - // the coinbase must pay the fees from the last transaction and the block reward at a minimum. - if ( pblock->vtx.size() < 1 || pblock->vtx[0].vout.size() < 1 ) - { - fprintf(stderr, "[%s:%d] missing coinbase.\n", ASSETCHAINS_SYMBOL, height); - return(-1); - } - else if ( pblock->vtx[0].vout[0].nValue < stakeTxValue ) - { - fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", ASSETCHAINS_SYMBOL, height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); - return(-1); - } - // set the pindex->segid as this is now fully validated to be a PoS block. - char voutaddr[64]; CTxDestination voutaddress; - if ( ExtractDestination(pblock->vtx.back().vout[0].scriptPubKey,voutaddress) ) - { - strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - segid = komodo_segid32(voutaddr) & 0x3f; - } - if ( pindex != 0 && segid >= 0 ) - { - pindex->segid = segid; - //fprintf(stderr,"PoS block set segid.%d <- %d\n",height,pindex->segid); - } - } - 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]; - 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); - } - } - 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 ) - { - // 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 ) - { - // Check the notarisation tx is to the crypto address. - if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 ) - { - fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height); - return(-1); - } - // Check min sigs. - int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; - numSN = komodo_notaries(notarypubkeys, height, pblock->nTime); - if ( pblock->vtx[1].vin.size() < numSN/5 ) - { - fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%lld\n",height,numSN/5,(long long)pblock->vtx[1].vin.size()); - return(-1); - } - } - } - -//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed); - if ( failed != 0 && possible == 0 && notaryid < 0 ) - return(-1); - else return(0); -} - -int32_t komodo_acpublic(uint32_t tiptime) -{ - int32_t acpublic = ASSETCHAINS_PUBLIC; CBlockIndex *pindex; - if ( acpublic == 0 ) - { - if ( tiptime == 0 ) - { - if ( (pindex= chainActive.LastTip()) != 0 ) - tiptime = pindex->nTime; - } - if ( (ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"ZEX") == 0) && tiptime >= KOMODO_SAPLING_DEADLINE ) - acpublic = 1; - } - return(acpublic); -} - -int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock) -{ - 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; - n = pblock->vtx.size(); - for (i=0; ivtx[i]; - if ( (m= tx.vin.size()) > 0 ) - { - for (j=0; j= 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 %s\n",dstr(tx.vout[j].nValue),CBitcoinAddress(address).ToString().c_str()); - } - script = (uint8_t *)&tx.vout[j].scriptPubKey[0]; - 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; - } - } - BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) - { - zfunds -= joinsplit.vpub_new; - zfunds += joinsplit.vpub_old; - sproutfunds -= joinsplit.vpub_new; - sproutfunds += joinsplit.vpub_old; - } - zfunds -= tx.valueBalance; - } - *zfundsp = zfunds; - *sproutfundsp = sproutfunds; - if ( ASSETCHAINS_SYMBOL[0] == 0 && (voutsum-vinsum) == 100003*SATOSHIDEN ) // 15 times - 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)); - return(voutsum - vinsum); -} - -int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) -{ - CBlockIndex *pindex; CBlock block; int64_t zfunds=0,sproutfunds=0,supply = 0; - //fprintf(stderr,"coinsupply %d\n",height); - *zfundsp = *sproutfundsp = 0; - if ( (pindex= komodo_chainactive(height)) != 0 ) - { - while ( pindex != 0 && pindex->GetHeight() > 0 ) - { - if ( pindex->newcoins == 0 && pindex->zfunds == 0 ) - { - if ( komodo_blockload(block,pindex) == 0 ) - pindex->newcoins = komodo_newcoins(&pindex->zfunds,&pindex->sproutfunds,pindex->GetHeight(),&block); - else - { - fprintf(stderr,"error loading block.%d\n",pindex->GetHeight()); - return(0); - } - } - supply += pindex->newcoins; - zfunds += pindex->zfunds; - 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)); - pindex = pindex->pprev; - } - } - *zfundsp = zfunds; - *sproutfundsp = sproutfunds; - 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); -} - -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot) -{ - static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; - int32_t PoSperc = 0, newStakerActive; - std::set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; - uint64_t cbPerc = *utxovaluep, tocoinbase = 0; - if (!EnsureWalletIsAvailable(0)) - return 0; - - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); - assert(pwalletMain != NULL); - *utxovaluep = 0; - memset(utxotxidp,0,sizeof(*utxotxidp)); - memset(utxovoutp,0,sizeof(*utxovoutp)); - memset(utxosig,0,72); - if ( (tipindex= chainActive.Tip()) == 0 ) - return(0); - nHeight = tipindex->GetHeight() + 1; - if ( (minage= nHeight*3) > 6000 ) // about 100 blocks - minage = 6000; - if ( *blocktimep < tipindex->nTime+60 ) - *blocktimep = tipindex->nTime+60; - komodo_segids(hashbuf,nHeight-101,100); - // this was for VerusHash PoS64 - //tmpTarget = komodo_PoWtarget(&PoSperc,bnTarget,nHeight,ASSETCHAINS_STAKED); - bool resetstaker = false; - if ( array != 0 ) - { - LOCK(cs_main); - CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()]; - CBlock block; CTxDestination addressout; - if ( ASSETCHAINS_MARMARA != 0 ) - resetstaker = true; - else if ( ReadBlockFromDisk(block, pblockindex, 1) && komodo_isPoS(&block, nHeight, &addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) - { - resetstaker = true; - fprintf(stderr, "[%s:%d] Reset ram staker after mining a block!\n",ASSETCHAINS_SYMBOL,nHeight); - } - } - - if ( resetstaker || array == 0 || time(NULL) > lasttime+600 ) - { - LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); - if ( array != 0 ) - { - free(array); - array = 0; - maxkp = numkp = 0; - lasttime = 0; - } - if ( ASSETCHAINS_MARMARA == 0 ) - { - BOOST_FOREACH(const COutput& out, vecOutputs) - { - if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) - { - fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),counter); - return(0); - } - counter++; - if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) - { - //fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); - continue; - } - CAmount nValue = out.tx->vout[out.i].nValue; - if ( nValue < COIN || !out.fSpendable ) - continue; - const CScript& pk = out.tx->vout[out.i].scriptPubKey; - if ( ExtractDestination(pk,address) != 0 ) - { - if ( IsMine(*pwalletMain,address) == 0 ) - continue; - if ( myGetTransaction(out.tx->GetHash(),tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) - { - array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); - //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); - } - } - } - } - else - { - struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk; - std::vector > unspentOutputs; - cp = CCinit(&C,EVAL_MARMARA); - mypk = pubkey2pk(Mypubkey()); - Marmarapk = GetUnspendable(cp,0); - GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk); - SetCCunspents(unspentOutputs,coinaddr,true); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) - { - txid = it->first.txhash; - vout = (int32_t)it->first.index; - if ( (nValue= it->second.satoshis) < COIN ) - continue; - if ( myGetTransaction(txid,tx,hashBlock) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) - { - const CScript &scriptPubKey = tx.vout[vout].scriptPubKey; - if ( DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht) != 0 && pk == mypk ) - { - array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey); - } - // else fprintf(stderr,"SKIP addutxo %.8f numkp.%d vs max.%d\n",(double)nValue/COIN,numkp,maxkp); - } - } - } - lasttime = (uint32_t)time(NULL); - //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); - } - block_from_future_rejecttime = (uint32_t)GetTime() + ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX; - for (i=winners=0; iGetHeight()+1 > nHeight ) - { - fprintf(stderr,"[%s:%d] chain tip changed during staking loop t.%u counter.%d\n",ASSETCHAINS_SYMBOL,nHeight,(uint32_t)time(NULL),i); - return(0); - } - kp = &array[i]; - eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc); - if ( eligible > 0 ) - { - besttime = 0; - if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,kp->address,PoSperc) ) - { - // have elegible utxo to stake with. - if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) - { - // is better than the previous best, so use it instead. - earliest = eligible; - best_scriptPubKey = kp->scriptPubKey; - *utxovaluep = (uint64_t)kp->nValue; - decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); - *utxovoutp = kp->vout; - *txtimep = kp->txtime; - } - /*if ( eligible < block_from_future_rejecttime ) - { - // better to scan all and choose earliest! - fprintf(stderr, "block_from_future_rejecttime.%u vs eligible.%u \n", block_from_future_rejecttime, eligible); - break; - } */ - } - } - } - if ( numkp < 500 && array != 0 ) - { - free(array); - array = 0; - maxkp = numkp = 0; - lasttime = 0; - } - if ( earliest != 0 ) - { - bool signSuccess; SignatureData sigdata; uint64_t txfee; uint8_t *ptr; uint256 revtxid,utxotxid; - auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - const CKeyStore& keystore = *pwalletMain; - txNew.vin.resize(1); - txNew.vout.resize(1); - txfee = 0; - for (i=0; i<32; i++) - ((uint8_t *)&revtxid)[i] = ((uint8_t *)utxotxidp)[31 - i]; - txNew.vin[0].prevout.hash = revtxid; - txNew.vin[0].prevout.n = *utxovoutp; - txNew.vout[0].scriptPubKey = best_scriptPubKey; - txNew.vout[0].nValue = *utxovaluep - txfee; - txNew.nLockTime = earliest; - txNew.nExpiryHeight = nHeight; - if ( (newStakerActive= komodo_newStakerActive(nHeight,earliest)) != 0 ) - { - if ( cbPerc > 0 && cbPerc <= 100 ) - { - tocoinbase = txNew.vout[0].nValue*cbPerc/100; - txNew.vout[0].nValue -= tocoinbase; - } - txNew.vout.resize(2); - txNew.vout[1].scriptPubKey = EncodeStakingOpRet(merkleroot); - txNew.vout[1].nValue = 0; - } - CTransaction txNewConst(txNew); - if ( ASSETCHAINS_MARMARA == 0 ) - { - signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); - UpdateTransaction(txNew,0,sigdata); - ptr = (uint8_t *)&sigdata.scriptSig[0]; - siglen = sigdata.scriptSig.size(); - for (i=0; i 0 ) - signSuccess = true; - else signSuccess = false; - } - if (!signSuccess) - fprintf(stderr,"failed to create signature\n"); - else - *blocktimep = earliest; - } - return(siglen); -} +bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height); + +uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); + +int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len); + +uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len); + +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); + +uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height); + +bool komodo_appendACscriptpub(); + +void GetKomodoEarlytxidScriptPub(); + +int64_t komodo_checkcommission(CBlock *pblock,int32_t height); + +int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,int32_t height); + +int32_t komodo_acpublic(uint32_t tiptime); + +int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,CBlock *pblock); + +int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); + +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); + +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep, + uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); \ No newline at end of file diff --git a/src/komodo_cJSON.c b/src/komodo_cJSON.c index 10140ad0232..0e71ae56736 100644 --- a/src/komodo_cJSON.c +++ b/src/komodo_cJSON.c @@ -21,13 +21,9 @@ THE SOFTWARE. */ -/* cJSON */ -/* JSON parser in C. */ #include -#include "cJSON.h" #include "komodo_cJSON.h" -#include "cJSON.c" #ifndef DBL_EPSILON #define DBL_EPSILON 2.2204460492503131E-16 diff --git a/src/komodo_cJSON.h b/src/komodo_cJSON.h index 3586b5cbf5b..3c463426dff 100644 --- a/src/komodo_cJSON.h +++ b/src/komodo_cJSON.h @@ -34,9 +34,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef komodo_cJSON__h -#define komodo_cJSON__h +#pragma once #include #include @@ -48,7 +46,10 @@ #include "cJSON.h" -//#include "../crypto777/OS_portable.h" +#ifndef SATOSHIDEN +#define SATOSHIDEN ((uint64_t)100000000L) +#define dstr(x) ((double)(x) / SATOSHIDEN) +#endif #define MAX_JSON_FIELD 4096 // on the big side @@ -57,11 +58,7 @@ extern "C" { #endif -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif +#include "komodo_cutils.h" /* Macros for creating things quickly. */ #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) @@ -141,8 +138,8 @@ extern "C" #define jfieldname get_cJSON_fieldname + long stripquotes(char *str); + #ifdef __cplusplus } #endif - -#endif diff --git a/src/komodo_ccdata.cpp b/src/komodo_ccdata.cpp new file mode 100644 index 00000000000..f56c6a68f39 --- /dev/null +++ b/src/komodo_ccdata.cpp @@ -0,0 +1,267 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ + +#include "komodo_globals.h" +#include "komodo_ccdata.h" + +struct komodo_ccdata *CC_data; +int32_t CC_firstheight; + +uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); // in primitives/block.h + +uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) +{ + static uint256 zero; CBlockIndex *pindex; int32_t i; std::vector tree, leaves; + bool fMutated; + MoMdepth &= 0xffff; // In case it includes the ccid + if ( MoMdepth >= height ) + return(zero); + for (i=0; ihashMerkleRoot); + else + return(zero); + } + return BuildMerkleTree(&fMutated, leaves, tree); +} + +struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi) +{ + struct komodo_ccdata_entry *allMoMs=0; struct komodo_ccdata *ccdata,*tmpptr; int32_t i,num,max; + bool fMutated; std::vector tree, leaves; + num = max = 0; + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height <= kmdendi && ccdata->MoMdata.height >= kmdstarti ) + { + if ( num >= max ) + { + max += 100; + allMoMs = (struct komodo_ccdata_entry *)realloc(allMoMs,max * sizeof(*allMoMs)); + } + allMoMs[num].MoM = ccdata->MoMdata.MoM; + allMoMs[num].notarized_height = ccdata->MoMdata.notarized_height; + allMoMs[num].kmdheight = ccdata->MoMdata.height; + allMoMs[num].txi = ccdata->MoMdata.txi; + strcpy(allMoMs[num].symbol,ccdata->symbol); + num++; + } + if ( ccdata->MoMdata.height < kmdstarti ) + break; + } + portable_mutex_unlock(&KOMODO_CC_mutex); + if ( (*nump= num) > 0 ) + { + for (i=0; i= 0) { + if ( mdata->numpairs >= maxpairs ) + { + maxpairs += 100; + mdata->pairs = (struct komodo_ccdatapair *)realloc(mdata->pairs,sizeof(*mdata->pairs)*maxpairs); + //fprintf(stderr,"pairs reallocated to %p num.%d\n",mdata->pairs,mdata->numpairs); + } + } else { + fprintf(stderr,"komodo_addpair.maxpairs %d must be >= 0\n",(int32_t)maxpairs); + return(-1); + } + mdata->pairs[mdata->numpairs].notarized_height = notarized_height; + mdata->pairs[mdata->numpairs].MoMoMoffset = offset; + mdata->numpairs++; + return(maxpairs); +} + +int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height) +{ + uint8_t hexdata[8192]; struct komodo_ccdata *ccdata,*tmpptr; int32_t len,maxpairs,i,retval=-1,depth,starti,endi,CCid=0; struct komodo_ccdata_entry *allMoMs; + starti = endi = depth = len = maxpairs = 0; + hexstr[0] = 0; + if ( sizeof(hexdata)*2+1 > hexsize ) + { + fprintf(stderr,"hexsize.%d too small for %d\n",hexsize,(int32_t)sizeof(hexdata)); + return(-1); + } + memset(mdata,0,sizeof(*mdata)); + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height < kmdheight ) + { + //fprintf(stderr,"%s notarized.%d kmd.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height,ccdata->MoMdata.height); + if ( strcmp(ccdata->symbol,symbol) == 0 ) + { + if ( endi == 0 ) + { + endi = ccdata->MoMdata.height; + CCid = ccdata->CCid; + } + if ( (mdata->numpairs == 1 && notarized_height == 0) || ccdata->MoMdata.notarized_height <= notarized_height ) + { + starti = ccdata->MoMdata.height + 1; + if ( notarized_height == 0 ) + notarized_height = ccdata->MoMdata.notarized_height; + break; + } + } + starti = ccdata->MoMdata.height; + } + } + portable_mutex_unlock(&KOMODO_CC_mutex); + mdata->kmdstarti = starti; + mdata->kmdendi = endi; + if ( starti != 0 && endi != 0 && endi >= starti ) + { + if ( (allMoMs= komodo_allMoMs(&depth,&mdata->MoMoM,starti,endi)) != 0 ) + { + mdata->MoMoMdepth = depth; + for (i=0; inumpairs > 0 ) + { + len += iguana_rwnum(1,&hexdata[len],sizeof(CCid),(uint8_t *)&CCid); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdstarti); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdendi); + len += iguana_rwbignum(1,&hexdata[len],sizeof(mdata->MoMoM),(uint8_t *)&mdata->MoMoM); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->MoMoMdepth); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->numpairs); + for (i=0; inumpairs; i++) + { + if ( len + sizeof(uint32_t)*2 > sizeof(hexdata) ) + { + fprintf(stderr,"%s %d %d i.%d of %d exceeds hexdata.%d\n",symbol,kmdheight,notarized_height,i,mdata->numpairs,(int32_t)sizeof(hexdata)); + break; + } + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].notarized_height); + len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].MoMoMoffset); + } + if ( i == mdata->numpairs && len*2+1 < hexsize ) + { + init_hexbytes_noT(hexstr,hexdata,len); + //fprintf(stderr,"hexstr.(%s)\n",hexstr); + retval = 0; + } else fprintf(stderr,"%s %d %d too much hexdata[%d] for hexstr[%d]\n",symbol,kmdheight,notarized_height,len,hexsize); + } + free(allMoMs); + } + } + return(retval); +} + +void komodo_purge_ccdata(int32_t height) +{ + struct komodo_ccdata *ccdata,*tmpptr; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + portable_mutex_lock(&KOMODO_CC_mutex); + DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) + { + if ( ccdata->MoMdata.height >= height ) + { + printf("PURGE %s notarized.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height); + DL_DELETE(CC_data,ccdata); + free(ccdata); + } else break; + } + portable_mutex_unlock(&KOMODO_CC_mutex); + } + else + { + // purge notarized data + } +} + +// this is just a demo of ccdata processing to create example data for the MoMoM and allMoMs calls +int32_t komodo_rwccdata(char *thischain,int32_t rwflag,struct komodo_ccdata *ccdata,struct komodo_ccdataMoMoM *MoMoMdata) +{ + uint256 hash,zero; bits256 tmp; int32_t i,nonz; struct komodo_ccdata *ptr; struct notarized_checkpoint *np; + return(0); // disable this path as libscott method is much better + if ( rwflag == 0 ) + { + // load from disk + } + else + { + // write to disk + } + if ( ccdata->MoMdata.height > 0 && (CC_firstheight == 0 || ccdata->MoMdata.height < CC_firstheight) ) + CC_firstheight = ccdata->MoMdata.height; + for (nonz=i=0; i<32; i++) + { + if ( (tmp.bytes[i]= ((uint8_t *)&ccdata->MoMdata.MoM)[31-i]) != 0 ) + nonz++; + } + if ( nonz == 0 ) + return(0); + memcpy(&hash,&tmp,sizeof(hash)); + //fprintf(stderr,"[%s] ccdata.%s id.%d notarized_ht.%d MoM.%s height.%d/t%d\n",ASSETCHAINS_SYMBOL,ccdata->symbol,ccdata->CCid,ccdata->MoMdata.notarized_height,hash.ToString().c_str(),ccdata->MoMdata.height,ccdata->MoMdata.txi); + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( CC_data != 0 && (CC_data->MoMdata.height > ccdata->MoMdata.height || (CC_data->MoMdata.height == ccdata->MoMdata.height && CC_data->MoMdata.txi >= ccdata->MoMdata.txi)) ) + { + printf("out of order detected? SKIP CC_data ht.%d/txi.%d vs ht.%d/txi.%d\n",CC_data->MoMdata.height,CC_data->MoMdata.txi,ccdata->MoMdata.height,ccdata->MoMdata.txi); + } + else + { + ptr = (struct komodo_ccdata *)calloc(1,sizeof(*ptr)); + *ptr = *ccdata; + portable_mutex_lock(&KOMODO_CC_mutex); + DL_PREPEND(CC_data,ptr); + portable_mutex_unlock(&KOMODO_CC_mutex); + } + } + else + { + if ( MoMoMdata != 0 && MoMoMdata->pairs != 0 ) + { + for (i=0; inumpairs; i++) + { + if ( (np= komodo_npptr(MoMoMdata->pairs[i].notarized_height)) != 0 ) + { + memset(&zero,0,sizeof(zero)); + if ( memcmp(&np->MoMoM,&zero,sizeof(np->MoMoM)) == 0 ) + { + np->MoMoM = MoMoMdata->MoMoM; + np->MoMoMdepth = MoMoMdata->MoMoMdepth; + np->MoMoMoffset = MoMoMdata->MoMoMoffset; + np->kmdstarti = MoMoMdata->kmdstarti; + np->kmdendi = MoMoMdata->kmdendi; + } + else if ( memcmp(&np->MoMoM,&MoMoMdata->MoMoM,sizeof(np->MoMoM)) != 0 || np->MoMoMdepth != MoMoMdata->MoMoMdepth || np->MoMoMoffset != MoMoMdata->MoMoMoffset || np->kmdstarti != MoMoMdata->kmdstarti || np->kmdendi != MoMoMdata->kmdendi ) + { + fprintf(stderr,"preexisting MoMoM mismatch: %s (%d %d %d %d) vs %s (%d %d %d %d)\n",np->MoMoM.ToString().c_str(),np->MoMoMdepth,np->MoMoMoffset,np->kmdstarti,np->kmdendi,MoMoMdata->MoMoM.ToString().c_str(),MoMoMdata->MoMoMdepth,MoMoMdata->MoMoMoffset,MoMoMdata->kmdstarti,MoMoMdata->kmdendi); + } + } + } + } + } + return(1); +} diff --git a/src/komodo_ccdata.h b/src/komodo_ccdata.h index 3969532fd7f..74a684f426f 100644 --- a/src/komodo_ccdata.h +++ b/src/komodo_ccdata.h @@ -12,258 +12,19 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once -#ifndef H_KOMODOCCDATA_H -#define H_KOMODOCCDATA_H +#include "komodo.h" -struct komodo_ccdata *CC_data; -int32_t CC_firstheight; +uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); -uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); +struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); -uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) -{ - static uint256 zero; CBlockIndex *pindex; int32_t i; std::vector tree, leaves; - bool fMutated; - MoMdepth &= 0xffff; // In case it includes the ccid - if ( MoMdepth >= height ) - return(zero); - for (i=0; ihashMerkleRoot); - else - return(zero); - } - return BuildMerkleTree(&fMutated, leaves, tree); -} +int32_t komodo_addpair(struct komodo_ccdataMoMoM *mdata,int32_t notarized_height,int32_t offset,int32_t maxpairs); -struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi) -{ - struct komodo_ccdata_entry *allMoMs=0; struct komodo_ccdata *ccdata,*tmpptr; int32_t i,num,max; - bool fMutated; std::vector tree, leaves; - num = max = 0; - portable_mutex_lock(&KOMODO_CC_mutex); - DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) - { - if ( ccdata->MoMdata.height <= kmdendi && ccdata->MoMdata.height >= kmdstarti ) - { - if ( num >= max ) - { - max += 100; - allMoMs = (struct komodo_ccdata_entry *)realloc(allMoMs,max * sizeof(*allMoMs)); - } - allMoMs[num].MoM = ccdata->MoMdata.MoM; - allMoMs[num].notarized_height = ccdata->MoMdata.notarized_height; - allMoMs[num].kmdheight = ccdata->MoMdata.height; - allMoMs[num].txi = ccdata->MoMdata.txi; - strcpy(allMoMs[num].symbol,ccdata->symbol); - num++; - } - if ( ccdata->MoMdata.height < kmdstarti ) - break; - } - portable_mutex_unlock(&KOMODO_CC_mutex); - if ( (*nump= num) > 0 ) - { - for (i=0; i= 0) { - if ( mdata->numpairs >= maxpairs ) - { - maxpairs += 100; - mdata->pairs = (struct komodo_ccdatapair *)realloc(mdata->pairs,sizeof(*mdata->pairs)*maxpairs); - //fprintf(stderr,"pairs reallocated to %p num.%d\n",mdata->pairs,mdata->numpairs); - } - } else { - fprintf(stderr,"komodo_addpair.maxpairs %d must be >= 0\n",(int32_t)maxpairs); - return(-1); - } - mdata->pairs[mdata->numpairs].notarized_height = notarized_height; - mdata->pairs[mdata->numpairs].MoMoMoffset = offset; - mdata->numpairs++; - return(maxpairs); -} - -int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height) -{ - uint8_t hexdata[8192]; struct komodo_ccdata *ccdata,*tmpptr; int32_t len,maxpairs,i,retval=-1,depth,starti,endi,CCid=0; struct komodo_ccdata_entry *allMoMs; - starti = endi = depth = len = maxpairs = 0; - hexstr[0] = 0; - if ( sizeof(hexdata)*2+1 > hexsize ) - { - fprintf(stderr,"hexsize.%d too small for %d\n",hexsize,(int32_t)sizeof(hexdata)); - return(-1); - } - memset(mdata,0,sizeof(*mdata)); - portable_mutex_lock(&KOMODO_CC_mutex); - DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) - { - if ( ccdata->MoMdata.height < kmdheight ) - { - //fprintf(stderr,"%s notarized.%d kmd.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height,ccdata->MoMdata.height); - if ( strcmp(ccdata->symbol,symbol) == 0 ) - { - if ( endi == 0 ) - { - endi = ccdata->MoMdata.height; - CCid = ccdata->CCid; - } - if ( (mdata->numpairs == 1 && notarized_height == 0) || ccdata->MoMdata.notarized_height <= notarized_height ) - { - starti = ccdata->MoMdata.height + 1; - if ( notarized_height == 0 ) - notarized_height = ccdata->MoMdata.notarized_height; - break; - } - } - starti = ccdata->MoMdata.height; - } - } - portable_mutex_unlock(&KOMODO_CC_mutex); - mdata->kmdstarti = starti; - mdata->kmdendi = endi; - if ( starti != 0 && endi != 0 && endi >= starti ) - { - if ( (allMoMs= komodo_allMoMs(&depth,&mdata->MoMoM,starti,endi)) != 0 ) - { - mdata->MoMoMdepth = depth; - for (i=0; inumpairs > 0 ) - { - len += iguana_rwnum(1,&hexdata[len],sizeof(CCid),(uint8_t *)&CCid); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdstarti); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->kmdendi); - len += iguana_rwbignum(1,&hexdata[len],sizeof(mdata->MoMoM),(uint8_t *)&mdata->MoMoM); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->MoMoMdepth); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->numpairs); - for (i=0; inumpairs; i++) - { - if ( len + sizeof(uint32_t)*2 > sizeof(hexdata) ) - { - fprintf(stderr,"%s %d %d i.%d of %d exceeds hexdata.%d\n",symbol,kmdheight,notarized_height,i,mdata->numpairs,(int32_t)sizeof(hexdata)); - break; - } - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].notarized_height); - len += iguana_rwnum(1,&hexdata[len],sizeof(uint32_t),(uint8_t *)&mdata->pairs[i].MoMoMoffset); - } - if ( i == mdata->numpairs && len*2+1 < hexsize ) - { - init_hexbytes_noT(hexstr,hexdata,len); - //fprintf(stderr,"hexstr.(%s)\n",hexstr); - retval = 0; - } else fprintf(stderr,"%s %d %d too much hexdata[%d] for hexstr[%d]\n",symbol,kmdheight,notarized_height,len,hexsize); - } - free(allMoMs); - } - } - return(retval); -} - -void komodo_purge_ccdata(int32_t height) -{ - struct komodo_ccdata *ccdata,*tmpptr; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - portable_mutex_lock(&KOMODO_CC_mutex); - DL_FOREACH_SAFE(CC_data,ccdata,tmpptr) - { - if ( ccdata->MoMdata.height >= height ) - { - printf("PURGE %s notarized.%d\n",ccdata->symbol,ccdata->MoMdata.notarized_height); - DL_DELETE(CC_data,ccdata); - free(ccdata); - } else break; - } - portable_mutex_unlock(&KOMODO_CC_mutex); - } - else - { - // purge notarized data - } -} +void komodo_purge_ccdata(int32_t height); // this is just a demo of ccdata processing to create example data for the MoMoM and allMoMs calls -int32_t komodo_rwccdata(char *thischain,int32_t rwflag,struct komodo_ccdata *ccdata,struct komodo_ccdataMoMoM *MoMoMdata) -{ - uint256 hash,zero; bits256 tmp; int32_t i,nonz; struct komodo_ccdata *ptr; struct notarized_checkpoint *np; - return(0); // disable this path as libscott method is much better - if ( rwflag == 0 ) - { - // load from disk - } - else - { - // write to disk - } - if ( ccdata->MoMdata.height > 0 && (CC_firstheight == 0 || ccdata->MoMdata.height < CC_firstheight) ) - CC_firstheight = ccdata->MoMdata.height; - for (nonz=i=0; i<32; i++) - { - if ( (tmp.bytes[i]= ((uint8_t *)&ccdata->MoMdata.MoM)[31-i]) != 0 ) - nonz++; - } - if ( nonz == 0 ) - return(0); - memcpy(&hash,&tmp,sizeof(hash)); - //fprintf(stderr,"[%s] ccdata.%s id.%d notarized_ht.%d MoM.%s height.%d/t%d\n",ASSETCHAINS_SYMBOL,ccdata->symbol,ccdata->CCid,ccdata->MoMdata.notarized_height,hash.ToString().c_str(),ccdata->MoMdata.height,ccdata->MoMdata.txi); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( CC_data != 0 && (CC_data->MoMdata.height > ccdata->MoMdata.height || (CC_data->MoMdata.height == ccdata->MoMdata.height && CC_data->MoMdata.txi >= ccdata->MoMdata.txi)) ) - { - printf("out of order detected? SKIP CC_data ht.%d/txi.%d vs ht.%d/txi.%d\n",CC_data->MoMdata.height,CC_data->MoMdata.txi,ccdata->MoMdata.height,ccdata->MoMdata.txi); - } - else - { - ptr = (struct komodo_ccdata *)calloc(1,sizeof(*ptr)); - *ptr = *ccdata; - portable_mutex_lock(&KOMODO_CC_mutex); - DL_PREPEND(CC_data,ptr); - portable_mutex_unlock(&KOMODO_CC_mutex); - } - } - else - { - if ( MoMoMdata != 0 && MoMoMdata->pairs != 0 ) - { - for (i=0; inumpairs; i++) - { - if ( (np= komodo_npptr(MoMoMdata->pairs[i].notarized_height)) != 0 ) - { - memset(&zero,0,sizeof(zero)); - if ( memcmp(&np->MoMoM,&zero,sizeof(np->MoMoM)) == 0 ) - { - np->MoMoM = MoMoMdata->MoMoM; - np->MoMoMdepth = MoMoMdata->MoMoMdepth; - np->MoMoMoffset = MoMoMdata->MoMoMoffset; - np->kmdstarti = MoMoMdata->kmdstarti; - np->kmdendi = MoMoMdata->kmdendi; - } - else if ( memcmp(&np->MoMoM,&MoMoMdata->MoMoM,sizeof(np->MoMoM)) != 0 || np->MoMoMdepth != MoMoMdata->MoMoMdepth || np->MoMoMoffset != MoMoMdata->MoMoMoffset || np->kmdstarti != MoMoMdata->kmdstarti || np->kmdendi != MoMoMdata->kmdendi ) - { - fprintf(stderr,"preexisting MoMoM mismatch: %s (%d %d %d %d) vs %s (%d %d %d %d)\n",np->MoMoM.ToString().c_str(),np->MoMoMdepth,np->MoMoMoffset,np->kmdstarti,np->kmdendi,MoMoMdata->MoMoM.ToString().c_str(),MoMoMdata->MoMoMdepth,MoMoMdata->MoMoMoffset,MoMoMdata->kmdstarti,MoMoMdata->kmdendi); - } - } - } - } - } - return(1); -} - -#endif +int32_t komodo_rwccdata(char *thischain,int32_t rwflag,struct komodo_ccdata *ccdata,struct komodo_ccdataMoMoM *MoMoMdata); diff --git a/src/komodo_curve25519.cpp b/src/komodo_curve25519.cpp new file mode 100644 index 00000000000..1d32fdbd450 --- /dev/null +++ b/src/komodo_curve25519.cpp @@ -0,0 +1,267 @@ +#include "komodo_utils.h" // for vcalc_sha256 + +#include "komodo_curve25519.h" + +void store_limb(uint8_t *out,uint64_t in) +{ + int32_t i; + for (i=0; i<8; i++,in>>=8) + out[i] = (in & 0xff); +} + +// Take a little-endian, 32-byte number and expand it into polynomial form +bits320 fexpand(bits256 basepoint) +{ + bits320 out; + out.ulongs[0] = load_limb(basepoint.bytes) & 0x7ffffffffffffLL; + out.ulongs[1] = (load_limb(basepoint.bytes+6) >> 3) & 0x7ffffffffffffLL; + out.ulongs[2] = (load_limb(basepoint.bytes+12) >> 6) & 0x7ffffffffffffLL; + out.ulongs[3] = (load_limb(basepoint.bytes+19) >> 1) & 0x7ffffffffffffLL; + out.ulongs[4] = (load_limb(basepoint.bytes+24) >> 12) & 0x7ffffffffffffLL; + return(out); +} + +// Multiply two numbers: output = in2 * in +// output must be distinct to both inputs. The inputs are reduced coefficient form, the output is not. +// Assumes that in[i] < 2**55 and likewise for in2. On return, output[i] < 2**52 +bits320 fmul(const bits320 in2,const bits320 in) +{ + uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; bits320 out; + r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; + s0 = in2.ulongs[0], s1 = in2.ulongs[1], s2 = in2.ulongs[2], s3 = in2.ulongs[3], s4 = in2.ulongs[4]; + t[0] = ((uint128_t) r0) * s0; + t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0; + t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1; + t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1; + t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2; + r4 *= 19, r1 *= 19, r2 *= 19, r3 *= 19; + t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2; + t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3; + t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4; + t[3] += ((uint128_t) r4) * s4; + r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); + t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); + t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); + t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffLL; c = (uint64_t)(t[3] >> 51); + t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; + r2 += c; + out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; + return(out); +} + +bits320 fsquare_times(const bits320 in,uint64_t count) +{ + uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,c,d0,d1,d2,d4,d419; bits320 out; + r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; + do + { + d0 = r0 * 2; + d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; + d4 = d419 * 2; + t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); + t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); + t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); + t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); + t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); + + r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); + t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); + t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); + t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffL; c = (uint64_t)(t[3] >> 51); + t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; + r2 += c; + } while( --count ); + out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; + return(out); +} + +// donna: Take a fully reduced polynomial form number and contract it into a little-endian, 32-byte array +bits256 fcontract(const bits320 input) +{ + uint128_t t[5]; int32_t i; bits256 out; + for (i=0; i<5; i++) + t[i] = input.ulongs[i]; + fcontract_iter(t,1), fcontract_iter(t,1); + // donna: now t is between 0 and 2^255-1, properly carried. + // donna: case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. + t[0] += 19, fcontract_iter(t,1); + // now between 19 and 2^255-1 in both cases, and offset by 19. + t[0] += 0x8000000000000 - 19; + for (i=1; i<5; i++) + t[i] += 0x8000000000000 - 1; + // now between 2^255 and 2^256-20, and offset by 2^255. + fcontract_iter(t,0); + store_limb(out.bytes,t[0] | (t[1] << 51)); + store_limb(out.bytes+8,(t[1] >> 13) | (t[2] << 38)); + store_limb(out.bytes+16,(t[2] >> 26) | (t[3] << 25)); + store_limb(out.bytes+24,(t[3] >> 39) | (t[4] << 12)); + return(out); +} + +bits256 curve25519(bits256 mysecret,bits256 basepoint) +{ + bits320 bp,x,z; + mysecret.bytes[0] &= 0xf8, mysecret.bytes[31] &= 0x7f, mysecret.bytes[31] |= 0x40; + bp = fexpand(basepoint); + cmult(&x,&z,mysecret,bp); + return(fcontract(fmul(x,crecip(z)))); +} + +// Calculates nQ where Q is the x-coordinate of a point on the curve +// resultx/resultz: the x coordinate of the resulting curve point (short form) +// n: a little endian, 32-byte number +// q: a point of the curve (short form) +void cmult(bits320 *resultx,bits320 *resultz,bits256 secret,const bits320 q) +{ + int32_t i,j; bits320 a,b,c,d,e,f,g,h,*t; + bits320 Zero320bits,One320bits, *nqpqx = &a,*nqpqz = &b,*nqx = &c,*nqz = &d,*nqpqx2 = &e,*nqpqz2 = &f,*nqx2 = &g,*nqz2 = &h; + memset(&Zero320bits,0,sizeof(Zero320bits)); + memset(&One320bits,0,sizeof(One320bits)), One320bits.ulongs[0] = 1; + a = d = e = g = Zero320bits, b = c = f = h = One320bits; + *nqpqx = q; + for (i=0; i<32; i++) + { + uint8_t byte = secret.bytes[31 - i]; + for (j=0; j<8; j++) + { + const uint64_t bit = byte >> 7; + swap_conditional(nqx,nqpqx,bit), swap_conditional(nqz,nqpqz,bit); + fmonty(nqx2,nqz2,nqpqx2,nqpqz2,nqx,nqz,nqpqx,nqpqz,q); + swap_conditional(nqx2,nqpqx2,bit), swap_conditional(nqz2,nqpqz2,bit); + t = nqx, nqx = nqx2, nqx2 = t; + t = nqz, nqz = nqz2, nqz2 = t; + t = nqpqx, nqpqx = nqpqx2, nqpqx2 = t; + t = nqpqz, nqpqz = nqpqz2, nqpqz2 = t; + byte <<= 1; + } + } + *resultx = *nqx, *resultz = *nqz; +} + +bits256 rand256(int32_t privkeyflag) +{ + bits256 randval; + #ifndef __WIN32 + OS_randombytes(randval.bytes,sizeof(randval)); + #else + randombytes_buf(randval.bytes,sizeof(randval)); + #endif + if ( privkeyflag != 0 ) + randval.bytes[0] &= 0xf8, randval.bytes[31] &= 0x7f, randval.bytes[31] |= 0x40; + return(randval); +} + +bits256 curve25519_basepoint9() +{ + bits256 basepoint; + memset(&basepoint,0,sizeof(basepoint)); + basepoint.bytes[0] = 9; + return(basepoint); +} + +bits256 curve25519_keypair(bits256 *pubkeyp) +{ + bits256 privkey; + privkey = rand256(1); + *pubkeyp = curve25519(privkey,curve25519_basepoint9()); + //printf("[%llx %llx] ",privkey.txid,(*pubkeyp).txid); + return(privkey); +} + +bits256 curve25519_shared(bits256 privkey,bits256 otherpub) +{ + bits256 shared,hash; + shared = curve25519(privkey,otherpub); + vcalc_sha256(0,hash.bytes,shared.bytes,sizeof(shared)); + //printf("priv.%llx pub.%llx shared.%llx -> hash.%llx\n",privkey.txid,pubkey.txid,shared.txid,hash.txid); + //hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; + return(hash); +} + +int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t *basepoint) +{ + bits256 val,p,bp; + memcpy(p.bytes,secret,sizeof(p)); + memcpy(bp.bytes,basepoint,sizeof(bp)); + val = curve25519(p,bp); + memcpy(mypublic,val.bytes,sizeof(val)); + return(0); +} + +uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen) +{ + static uint8_t basepoint[32] = {9}; + uint64_t addr; uint8_t hash[32]; + if ( pass != 0 && passlen != 0 ) + vcalc_sha256(0,mysecret,pass,passlen); + mysecret[0] &= 248, mysecret[31] &= 127, mysecret[31] |= 64; + curve25519_donna(mypublic,mysecret,basepoint); + vcalc_sha256(0,hash,mypublic,32); + memcpy(&addr,hash,sizeof(addr)); + return(addr); +} + +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase) +{ + uint256 privkey; + conv_NXTpassword((uint8_t *)&privkey,(uint8_t *)pubkeyp,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + return(privkey); +} + +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey) +{ + bits256 sig,hash,otherpub,checksig,pubkey,privkey; uint256 usig; + memcpy(&privkey,&_privkey,sizeof(privkey)); + vcalc_sha256(0,hash.bytes,buf,len); + otherpub = curve25519(hash,curve25519_basepoint9()); + pubkey = curve25519(privkey,curve25519_basepoint9()); + sig = curve25519_shared(privkey,otherpub); + checksig = curve25519_shared(hash,pubkey); + /*int32_t i; for (i=0; i "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&privkey)[i]); + printf(" -> "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&pubkey)[i]); + printf(" pubkey\n");*/ + memcpy(&usig,&sig,sizeof(usig)); + return(usig); +} + +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig) +{ + bits256 hash,checksig,pubkey; static uint256 zeroes; + memcpy(&pubkey,&_pubkey,sizeof(pubkey)); + if ( memcmp(&pubkey,&zeroes,sizeof(pubkey)) != 0 ) + { + vcalc_sha256(0,hash.bytes,buf,len); + checksig = curve25519_shared(hash,pubkey); + /*int32_t i; for (i=0; i "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&hash)[i]); + printf(" -> "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&pubkey)[i]); + printf(" verify pubkey\n"); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&sig)[i]); + printf(" sig vs"); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&checksig)[i]); + printf(" checksig\n");*/ + if ( memcmp(&checksig,&sig,sizeof(sig)) != 0 ) + return(-1); + //else printf("VALIDATED\n"); + } + return(0); +} diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index cba40561b8b..aabb6a163f3 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -12,9 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef H_KOMODO25519_H -#define H_KOMODO25519_H +#pragma once // derived from curve25519_donna #include @@ -23,6 +21,9 @@ #ifdef _WIN32 #include #endif + +#include "komodo_structs.h" + bits320 fmul(const bits320 in2,const bits320 in); bits320 fexpand(bits256 basepoint); bits256 fcontract(const bits320 input); @@ -49,12 +50,7 @@ static inline void fdifference_backwards(uint64_t *out,const uint64_t *in) out[i] = in[i] + two54m8 - out[i]; } -void store_limb(uint8_t *out,uint64_t in) -{ - int32_t i; - for (i=0; i<8; i++,in>>=8) - out[i] = (in & 0xff); -} +void store_limb(uint8_t *out,uint64_t in); static inline uint64_t load_limb(uint8_t *in) { @@ -70,16 +66,7 @@ static inline uint64_t load_limb(uint8_t *in) } // Take a little-endian, 32-byte number and expand it into polynomial form -bits320 fexpand(bits256 basepoint) -{ - bits320 out; - out.ulongs[0] = load_limb(basepoint.bytes) & 0x7ffffffffffffLL; - out.ulongs[1] = (load_limb(basepoint.bytes+6) >> 3) & 0x7ffffffffffffLL; - out.ulongs[2] = (load_limb(basepoint.bytes+12) >> 6) & 0x7ffffffffffffLL; - out.ulongs[3] = (load_limb(basepoint.bytes+19) >> 1) & 0x7ffffffffffffLL; - out.ulongs[4] = (load_limb(basepoint.bytes+24) >> 12) & 0x7ffffffffffffLL; - return(out); -} +bits320 fexpand(bits256 basepoint); #if __amd64__ // donna: special gcc mode for 128-bit integers. It's implemented on 64-bit platforms only as far as I know. @@ -103,62 +90,9 @@ static inline bits320 fscalar_product(const bits320 in,const uint64_t scalar) // Multiply two numbers: output = in2 * in // output must be distinct to both inputs. The inputs are reduced coefficient form, the output is not. // Assumes that in[i] < 2**55 and likewise for in2. On return, output[i] < 2**52 -bits320 fmul(const bits320 in2,const bits320 in) -{ - uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; bits320 out; - r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; - s0 = in2.ulongs[0], s1 = in2.ulongs[1], s2 = in2.ulongs[2], s3 = in2.ulongs[3], s4 = in2.ulongs[4]; - t[0] = ((uint128_t) r0) * s0; - t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0; - t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1; - t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1; - t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2; - r4 *= 19, r1 *= 19, r2 *= 19, r3 *= 19; - t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2; - t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3; - t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4; - t[3] += ((uint128_t) r4) * s4; - r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); - t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); - t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); - t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffLL; c = (uint64_t)(t[3] >> 51); - t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); - r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; - r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; - r2 += c; - out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; - return(out); -} +bits320 fmul(const bits320 in2,const bits320 in); -bits320 fsquare_times(const bits320 in,uint64_t count) -{ - uint128_t t[5]; uint64_t r0,r1,r2,r3,r4,c,d0,d1,d2,d4,d419; bits320 out; - r0 = in.ulongs[0], r1 = in.ulongs[1], r2 = in.ulongs[2], r3 = in.ulongs[3], r4 = in.ulongs[4]; - do - { - d0 = r0 * 2; - d1 = r1 * 2; - d2 = r2 * 2 * 19; - d419 = r4 * 19; - d4 = d419 * 2; - t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); - t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); - t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); - t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); - t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); - - r0 = (uint64_t)t[0] & 0x7ffffffffffffLL; c = (uint64_t)(t[0] >> 51); - t[1] += c; r1 = (uint64_t)t[1] & 0x7ffffffffffffLL; c = (uint64_t)(t[1] >> 51); - t[2] += c; r2 = (uint64_t)t[2] & 0x7ffffffffffffLL; c = (uint64_t)(t[2] >> 51); - t[3] += c; r3 = (uint64_t)t[3] & 0x7ffffffffffffL; c = (uint64_t)(t[3] >> 51); - t[4] += c; r4 = (uint64_t)t[4] & 0x7ffffffffffffLL; c = (uint64_t)(t[4] >> 51); - r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffffLL; - r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffffLL; - r2 += c; - } while( --count ); - out.ulongs[0] = r0, out.ulongs[1] = r1, out.ulongs[2] = r2, out.ulongs[3] = r3, out.ulongs[4] = r4; - return(out); -} +bits320 fsquare_times(const bits320 in,uint64_t count); static inline void fcontract_iter(uint128_t t[5],int32_t flag) { @@ -170,36 +104,9 @@ static inline void fcontract_iter(uint128_t t[5],int32_t flag) } // donna: Take a fully reduced polynomial form number and contract it into a little-endian, 32-byte array -bits256 fcontract(const bits320 input) -{ - uint128_t t[5]; int32_t i; bits256 out; - for (i=0; i<5; i++) - t[i] = input.ulongs[i]; - fcontract_iter(t,1), fcontract_iter(t,1); - // donna: now t is between 0 and 2^255-1, properly carried. - // donna: case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. - t[0] += 19, fcontract_iter(t,1); - // now between 19 and 2^255-1 in both cases, and offset by 19. - t[0] += 0x8000000000000 - 19; - for (i=1; i<5; i++) - t[i] += 0x8000000000000 - 1; - // now between 2^255 and 2^256-20, and offset by 2^255. - fcontract_iter(t,0); - store_limb(out.bytes,t[0] | (t[1] << 51)); - store_limb(out.bytes+8,(t[1] >> 13) | (t[2] << 38)); - store_limb(out.bytes+16,(t[2] >> 26) | (t[3] << 25)); - store_limb(out.bytes+24,(t[3] >> 39) | (t[4] << 12)); - return(out); -} +bits256 fcontract(const bits320 input); -bits256 curve25519(bits256 mysecret,bits256 basepoint) -{ - bits320 bp,x,z; - mysecret.bytes[0] &= 0xf8, mysecret.bytes[31] &= 0x7f, mysecret.bytes[31] |= 0x40; - bp = fexpand(basepoint); - cmult(&x,&z,mysecret,bp); - return(fcontract(fmul(x,crecip(z)))); -} +bits256 curve25519(bits256 mysecret,bits256 basepoint); #else // from curve25519-donna.c @@ -829,32 +736,7 @@ static inline void swap_conditional(bits320 *a,bits320 *b,uint64_t iswap) // resultx/resultz: the x coordinate of the resulting curve point (short form) // n: a little endian, 32-byte number // q: a point of the curve (short form) -void cmult(bits320 *resultx,bits320 *resultz,bits256 secret,const bits320 q) -{ - int32_t i,j; bits320 a,b,c,d,e,f,g,h,*t; - bits320 Zero320bits,One320bits, *nqpqx = &a,*nqpqz = &b,*nqx = &c,*nqz = &d,*nqpqx2 = &e,*nqpqz2 = &f,*nqx2 = &g,*nqz2 = &h; - memset(&Zero320bits,0,sizeof(Zero320bits)); - memset(&One320bits,0,sizeof(One320bits)), One320bits.ulongs[0] = 1; - a = d = e = g = Zero320bits, b = c = f = h = One320bits; - *nqpqx = q; - for (i=0; i<32; i++) - { - uint8_t byte = secret.bytes[31 - i]; - for (j=0; j<8; j++) - { - const uint64_t bit = byte >> 7; - swap_conditional(nqx,nqpqx,bit), swap_conditional(nqz,nqpqz,bit); - fmonty(nqx2,nqz2,nqpqx2,nqpqz2,nqx,nqz,nqpqx,nqpqz,q); - swap_conditional(nqx2,nqpqx2,bit), swap_conditional(nqz2,nqpqz2,bit); - t = nqx, nqx = nqx2, nqx2 = t; - t = nqz, nqz = nqz2, nqz2 = t; - t = nqpqx, nqpqx = nqpqx2, nqpqx2 = t; - t = nqpqz, nqpqz = nqpqz2, nqpqz2 = t; - byte <<= 1; - } - } - *resultx = *nqx, *resultz = *nqz; -} +void cmult(bits320 *resultx,bits320 *resultz,bits256 secret,const bits320 q); // Shamelessly copied from donna's code that copied djb's code, changed a little inline bits320 crecip(const bits320 z) @@ -888,126 +770,20 @@ inline bits320 crecip(const bits320 z) void OS_randombytes(unsigned char *x,long xlen); #endif -bits256 rand256(int32_t privkeyflag) -{ - bits256 randval; - #ifndef __WIN32 - OS_randombytes(randval.bytes,sizeof(randval)); - #else - randombytes_buf(randval.bytes,sizeof(randval)); - #endif - if ( privkeyflag != 0 ) - randval.bytes[0] &= 0xf8, randval.bytes[31] &= 0x7f, randval.bytes[31] |= 0x40; - return(randval); -} +bits256 rand256(int32_t privkeyflag); -bits256 curve25519_basepoint9() -{ - bits256 basepoint; - memset(&basepoint,0,sizeof(basepoint)); - basepoint.bytes[0] = 9; - return(basepoint); -} - -bits256 curve25519_keypair(bits256 *pubkeyp) -{ - bits256 privkey; - privkey = rand256(1); - *pubkeyp = curve25519(privkey,curve25519_basepoint9()); - //printf("[%llx %llx] ",privkey.txid,(*pubkeyp).txid); - return(privkey); -} +bits256 curve25519_basepoint9(); -bits256 curve25519_shared(bits256 privkey,bits256 otherpub) -{ - bits256 shared,hash; - shared = curve25519(privkey,otherpub); - vcalc_sha256(0,hash.bytes,shared.bytes,sizeof(shared)); - //printf("priv.%llx pub.%llx shared.%llx -> hash.%llx\n",privkey.txid,pubkey.txid,shared.txid,hash.txid); - //hash.bytes[0] &= 0xf8, hash.bytes[31] &= 0x7f, hash.bytes[31] |= 64; - return(hash); -} +bits256 curve25519_keypair(bits256 *pubkeyp); -int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t *basepoint) -{ - bits256 val,p,bp; - memcpy(p.bytes,secret,sizeof(p)); - memcpy(bp.bytes,basepoint,sizeof(bp)); - val = curve25519(p,bp); - memcpy(mypublic,val.bytes,sizeof(val)); - return(0); -} +bits256 curve25519_shared(bits256 privkey,bits256 otherpub); -uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen) -{ - static uint8_t basepoint[32] = {9}; - uint64_t addr; uint8_t hash[32]; - if ( pass != 0 && passlen != 0 ) - vcalc_sha256(0,mysecret,pass,passlen); - mysecret[0] &= 248, mysecret[31] &= 127, mysecret[31] |= 64; - curve25519_donna(mypublic,mysecret,basepoint); - vcalc_sha256(0,hash,mypublic,32); - memcpy(&addr,hash,sizeof(addr)); - return(addr); -} +int32_t curve25519_donna(uint8_t *mypublic,const uint8_t *secret,const uint8_t *basepoint); -uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase) -{ - uint256 privkey; - conv_NXTpassword((uint8_t *)&privkey,(uint8_t *)pubkeyp,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); - return(privkey); -} +uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen); -uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey) -{ - bits256 sig,hash,otherpub,checksig,pubkey,privkey; uint256 usig; - memcpy(&privkey,&_privkey,sizeof(privkey)); - vcalc_sha256(0,hash.bytes,buf,len); - otherpub = curve25519(hash,curve25519_basepoint9()); - pubkey = curve25519(privkey,curve25519_basepoint9()); - sig = curve25519_shared(privkey,otherpub); - checksig = curve25519_shared(hash,pubkey); - /*int32_t i; for (i=0; i "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&privkey)[i]); - printf(" -> "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" pubkey\n");*/ - memcpy(&usig,&sig,sizeof(usig)); - return(usig); -} +uint256 komodo_kvprivkey(uint256 *pubkeyp,char *passphrase); -int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig) -{ - bits256 hash,checksig,pubkey; static uint256 zeroes; - memcpy(&pubkey,&_pubkey,sizeof(pubkey)); - if ( memcmp(&pubkey,&zeroes,sizeof(pubkey)) != 0 ) - { - vcalc_sha256(0,hash.bytes,buf,len); - checksig = curve25519_shared(hash,pubkey); - /*int32_t i; for (i=0; i "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" -> "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" verify pubkey\n"); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&sig)[i]); - printf(" sig vs"); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&checksig)[i]); - printf(" checksig\n");*/ - if ( memcmp(&checksig,&sig,sizeof(sig)) != 0 ) - return(-1); - //else printf("VALIDATED\n"); - } - return(0); -} +uint256 komodo_kvsig(uint8_t *buf,int32_t len,uint256 _privkey); -#endif +int32_t komodo_kvsigverify(uint8_t *buf,int32_t len,uint256 _pubkey,uint256 sig); diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp new file mode 100644 index 00000000000..3265acf4348 --- /dev/null +++ b/src/komodo_events.cpp @@ -0,0 +1,222 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_globals.h" +#include "komodo_events.h" + +struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen) +{ + struct komodo_event *ep=0; uint16_t len = (uint16_t)(sizeof(*ep) + datalen); + if ( sp != 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + { + std::lock_guard lock(komodo_mutex); + ep = (struct komodo_event *)calloc(1,len); + ep->len = len; + ep->height = height; + ep->type = type; + strcpy(ep->symbol,symbol); + if ( datalen != 0 ) + memcpy(ep->space,data,datalen); + sp->Komodo_events = (struct komodo_event **)realloc(sp->Komodo_events,(1 + sp->Komodo_numevents) * sizeof(*sp->Komodo_events)); + sp->Komodo_events[sp->Komodo_numevents++] = ep; + } + return(ep); +} + +void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) +{ + static uint32_t counter; int32_t verified=0; char *coin; struct komodo_event_notarized N; + coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; + if ( IS_KOMODO_NOTARY != 0 && (verified= komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid)) < 0 ) + { + if ( counter++ < 100 ) + printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n",ASSETCHAINS_SYMBOL,height,notarizedheight,dest); + } + else if ( strcmp(symbol,coin) == 0 ) + { + if ( 0 && IS_KOMODO_NOTARY != 0 && verified != 0 ) + fprintf(stderr,"validated [%s] ht.%d notarized %d\n",coin,height,notarizedheight); + memset(&N,0,sizeof(N)); + N.blockhash = notarized_hash; + N.desttxid = notarized_desttxid; + N.notarizedheight = notarizedheight; + N.MoM = MoM; + N.MoMdepth = MoMdepth; + strncpy(N.dest,dest,sizeof(N.dest)-1); + komodo_eventadd(sp,height,symbol,KOMODO_EVENT_NOTARIZED,(uint8_t *)&N,sizeof(N)); + if ( sp != 0 ) + komodo_notarized_update(sp,height,notarizedheight,notarized_hash,notarized_desttxid,MoM,MoMdepth); + } +} + +/**** + * Add a pubkey event to state + * @param sp the state + * @param symbol the symbol + * @param height + * @param num + * @param pubkeys + */ +void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]) +{ + struct komodo_event_pubkeys P; + //printf("eventadd pubkeys ht.%d\n",height); + memset(&P,0,sizeof(P)); + P.num = num; + memcpy(P.pubkeys,pubkeys,33 * num); + komodo_eventadd(sp,height,symbol,KOMODO_EVENT_RATIFY,(uint8_t *)&P,(int32_t)(sizeof(P.num) + 33 * num)); + if ( sp != 0 ) + komodo_notarysinit(height,pubkeys,num); +} + +void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num) +{ + struct komodo_event_pricefeed F; + if ( num == sizeof(F.prices)/sizeof(*F.prices) ) + { + memset(&F,0,sizeof(F)); + F.num = num; + memcpy(F.prices,prices,sizeof(*F.prices) * num); + komodo_eventadd(sp,height,symbol,KOMODO_EVENT_PRICEFEED,(uint8_t *)&F,(int32_t)(sizeof(F.num) + sizeof(*F.prices) * num)); + if ( sp != 0 ) + komodo_pvals(height,prices,num); + } //else fprintf(stderr,"skip pricefeed[%d]\n",num); +} + +void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen) +{ + struct komodo_event_opreturn O; uint8_t *opret; + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + opret = (uint8_t *)calloc(1,sizeof(O) + opretlen + 16); + O.txid = txid; + O.value = value; + O.vout = vout; + memcpy(opret,&O,sizeof(O)); + memcpy(&opret[sizeof(O)],buf,opretlen); + O.oplen = (int32_t)(opretlen + sizeof(O)); + komodo_eventadd(sp,height,symbol,KOMODO_EVENT_OPRETURN,opret,O.oplen); + free(opret); + if ( sp != 0 ) + komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); + } +} + +/*** + * Undo an event + * NOTE: Jut rolls back the height if a KMDHEIGHT, otherwise does nothing + * @param sp the state + * @param ep the event + */ +void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) +{ + switch ( ep->type ) + { + case KOMODO_EVENT_RATIFY: printf("rewind of ratify, needs to be coded.%d\n",ep->height); break; + case KOMODO_EVENT_NOTARIZED: break; + case KOMODO_EVENT_KMDHEIGHT: + if ( ep->height <= sp->SAVEDHEIGHT ) + sp->SAVEDHEIGHT = ep->height; + break; + case KOMODO_EVENT_PRICEFEED: + // backtrack prices; + break; + case KOMODO_EVENT_OPRETURN: + // backtrack opreturns + break; + } +} + +/**** + * Roll backwards through the list of events, undoing them + * NOTE: The heart of this calls komodo_event_undo, which only lowers the sp->SAVEDHEIGHT + * @param sp the state + * @param symbol the symbol + * @param height the height + */ +void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) +{ + struct komodo_event *ep; + if ( sp != 0 ) + { + if ( ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) + { + printf("undo KOMODO_LASTMINED %d <- %d\n",KOMODO_LASTMINED,prevKOMODO_LASTMINED); + KOMODO_LASTMINED = prevKOMODO_LASTMINED; + prevKOMODO_LASTMINED = 0; + } + while ( sp->Komodo_events != 0 && sp->Komodo_numevents > 0 ) + { + if ( (ep= sp->Komodo_events[sp->Komodo_numevents-1]) != 0 ) + { + if ( ep->height < height ) // don't go lower than the passed-in height + break; + //printf("[%s] undo %s event.%c ht.%d for rewind.%d\n",ASSETCHAINS_SYMBOL,symbol,ep->type,ep->height,height); + komodo_event_undo(sp,ep); + sp->Komodo_numevents--; + // Q: When are these events deallocated? + } + } + } +} + +/** + * Set the SAVEDHEIGHT and CURRENT_HEIGHT if higher than what is in the state object + * @param sp the state + * @param kmdheight the desired kmdheight + * @param timestamp the timestamp + */ +void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp) +{ + if ( sp != 0 ) + { + if ( kmdheight > sp->SAVEDHEIGHT ) + { + sp->SAVEDHEIGHT = kmdheight; + sp->SAVEDTIMESTAMP = timestamp; + } + if ( kmdheight > sp->CURRENT_HEIGHT ) + sp->CURRENT_HEIGHT = kmdheight; + } +} + +/**** + * Add a new height + * NOTE: If kmdheight is a negative number, it will cause a rewind event to abs(kmdheight) + * @param sp the state + * @param symbol the symbol + * @param height the height + * @param kmdheight the kmdheight to add + * @param timestamp the timestamp + */ +void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp) +{ + uint32_t buf[2]; + if ( kmdheight > 0 ) + { + buf[0] = (uint32_t)kmdheight; + buf[1] = timestamp; + komodo_eventadd(sp,height,symbol,KOMODO_EVENT_KMDHEIGHT,(uint8_t *)buf,sizeof(buf)); + if ( sp != 0 ) + komodo_setkmdheight(sp,kmdheight,timestamp); + } + else + { + //fprintf(stderr,"REWIND kmdheight.%d\n",kmdheight); + kmdheight = -kmdheight; + komodo_eventadd(sp,height,symbol,KOMODO_EVENT_REWIND,(uint8_t *)&height,sizeof(height)); + if ( sp != 0 ) + komodo_event_rewind(sp,symbol,height); + } +} diff --git a/src/komodo_events.h b/src/komodo_events.h index 178ad04c27d..62462095d08 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -12,55 +12,15 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once -#ifndef H_KOMODOEVENTS_H -#define H_KOMODOEVENTS_H #include "komodo_defs.h" +#include "komodo.h" -struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen) -{ - struct komodo_event *ep=0; uint16_t len = (uint16_t)(sizeof(*ep) + datalen); - if ( sp != 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - { - std::lock_guard lock(komodo_mutex); - ep = (struct komodo_event *)calloc(1,len); - ep->len = len; - ep->height = height; - ep->type = type; - strcpy(ep->symbol,symbol); - if ( datalen != 0 ) - memcpy(ep->space,data,datalen); - sp->Komodo_events = (struct komodo_event **)realloc(sp->Komodo_events,(1 + sp->Komodo_numevents) * sizeof(*sp->Komodo_events)); - sp->Komodo_events[sp->Komodo_numevents++] = ep; - } - return(ep); -} +struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen); -void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) -{ - static uint32_t counter; int32_t verified=0; char *coin; struct komodo_event_notarized N; - coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; - if ( IS_KOMODO_NOTARY != 0 && (verified= komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid)) < 0 ) - { - if ( counter++ < 100 ) - printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n",ASSETCHAINS_SYMBOL,height,notarizedheight,dest); - } - else if ( strcmp(symbol,coin) == 0 ) - { - if ( 0 && IS_KOMODO_NOTARY != 0 && verified != 0 ) - fprintf(stderr,"validated [%s] ht.%d notarized %d\n",coin,height,notarizedheight); - memset(&N,0,sizeof(N)); - N.blockhash = notarized_hash; - N.desttxid = notarized_desttxid; - N.notarizedheight = notarizedheight; - N.MoM = MoM; - N.MoMdepth = MoMdepth; - strncpy(N.dest,dest,sizeof(N.dest)-1); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_NOTARIZED,(uint8_t *)&N,sizeof(N)); - if ( sp != 0 ) - komodo_notarized_update(sp,height,notarizedheight,notarized_hash,notarized_desttxid,MoM,MoMdepth); - } -} +void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash, + uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth); /**** * Add a pubkey event to state @@ -70,156 +30,44 @@ void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t heig * @param num * @param pubkeys */ -void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]) -{ - struct komodo_event_pubkeys P; - //printf("eventadd pubkeys ht.%d\n",height); - memset(&P,0,sizeof(P)); - P.num = num; - memcpy(P.pubkeys,pubkeys,33 * num); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_RATIFY,(uint8_t *)&P,(int32_t)(sizeof(P.num) + 33 * num)); - if ( sp != 0 ) - komodo_notarysinit(height,pubkeys,num); -} +void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]); -void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num) -{ - struct komodo_event_pricefeed F; - if ( num == sizeof(F.prices)/sizeof(*F.prices) ) - { - memset(&F,0,sizeof(F)); - F.num = num; - memcpy(F.prices,prices,sizeof(*F.prices) * num); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_PRICEFEED,(uint8_t *)&F,(int32_t)(sizeof(F.num) + sizeof(*F.prices) * num)); - if ( sp != 0 ) - komodo_pvals(height,prices,num); - } //else fprintf(stderr,"skip pricefeed[%d]\n",num); -} +void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num); -void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen) -{ - struct komodo_event_opreturn O; uint8_t *opret; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - opret = (uint8_t *)calloc(1,sizeof(O) + opretlen + 16); - O.txid = txid; - O.value = value; - O.vout = vout; - memcpy(opret,&O,sizeof(O)); - memcpy(&opret[sizeof(O)],buf,opretlen); - O.oplen = (int32_t)(opretlen + sizeof(O)); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_OPRETURN,opret,O.oplen); - free(opret); - if ( sp != 0 ) - komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); - } -} - -void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) -{ - switch ( ep->type ) - { - case KOMODO_EVENT_RATIFY: printf("rewind of ratify, needs to be coded.%d\n",ep->height); break; - case KOMODO_EVENT_NOTARIZED: break; - case KOMODO_EVENT_KMDHEIGHT: - if ( ep->height <= sp->SAVEDHEIGHT ) - sp->SAVEDHEIGHT = ep->height; - break; - case KOMODO_EVENT_PRICEFEED: - // backtrack prices; - break; - case KOMODO_EVENT_OPRETURN: - // backtrack opreturns - break; - } -} - -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) -{ - struct komodo_event *ep; - if ( sp != 0 ) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) - { - printf("undo KOMODO_LASTMINED %d <- %d\n",KOMODO_LASTMINED,prevKOMODO_LASTMINED); - KOMODO_LASTMINED = prevKOMODO_LASTMINED; - prevKOMODO_LASTMINED = 0; - } - while ( sp->Komodo_events != 0 && sp->Komodo_numevents > 0 ) - { - if ( (ep= sp->Komodo_events[sp->Komodo_numevents-1]) != 0 ) - { - if ( ep->height < height ) - break; - //printf("[%s] undo %s event.%c ht.%d for rewind.%d\n",ASSETCHAINS_SYMBOL,symbol,ep->type,ep->height,height); - komodo_event_undo(sp,ep); - sp->Komodo_numevents--; - } - } - } -} - -void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp) -{ - if ( sp != 0 ) - { - if ( kmdheight > sp->SAVEDHEIGHT ) - { - sp->SAVEDHEIGHT = kmdheight; - sp->SAVEDTIMESTAMP = timestamp; - } - if ( kmdheight > sp->CURRENT_HEIGHT ) - sp->CURRENT_HEIGHT = kmdheight; - } -} - -void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp) -{ - uint32_t buf[2]; - if ( kmdheight > 0 ) - { - buf[0] = (uint32_t)kmdheight; - buf[1] = timestamp; - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_KMDHEIGHT,(uint8_t *)buf,sizeof(buf)); - if ( sp != 0 ) - komodo_setkmdheight(sp,kmdheight,timestamp); - } - else - { - //fprintf(stderr,"REWIND kmdheight.%d\n",kmdheight); - kmdheight = -kmdheight; - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_REWIND,(uint8_t *)&height,sizeof(height)); - if ( sp != 0 ) - komodo_event_rewind(sp,symbol,height); - } -} +void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen); +/*** + * Undo an event + * NOTE: Jut rolls back the height if a KMDHEIGHT, otherwise does nothing + * @param sp the state + * @param ep the event + */ +void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep); -/*void komodo_eventadd_deposit(int32_t actionflag,char *symbol,int32_t height,uint64_t komodoshis,char *fiat,uint64_t fiatoshis,uint8_t rmd160[20],bits256 kmdtxid,uint16_t kmdvout,uint64_t price) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_DEPOSIT,kmdtxid,komodoshis,kmdvout,opret,opretlen); - } - - void komodo_eventadd_issued(int32_t actionflag,char *symbol,int32_t height,int32_t fiatheight,bits256 fiattxid,uint16_t fiatvout,bits256 kmdtxid,uint16_t kmdvout,uint64_t fiatoshis) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_ISSUED,fiattxid,fiatoshis,fiatvout,opret,opretlen); - } - - void komodo_eventadd_withdraw(int32_t actionflag,char *symbol,int32_t height,uint64_t komodoshis,char *fiat,uint64_t fiatoshis,uint8_t rmd160[20],bits256 fiattxid,int32_t fiatvout,uint64_t price) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_WITHDRAW,fiattxid,fiatoshis,fiatvout,opret,opretlen); - } - - void komodo_eventadd_redeemed(int32_t actionflag,char *symbol,int32_t height,bits256 kmdtxid,uint16_t kmdvout,int32_t fiatheight,bits256 fiattxid,uint16_t fiatvout,uint64_t komodoshis) - { - uint8_t opret[512]; uint16_t opretlen; - komodo_eventadd_opreturn(symbol,height,KOMODO_OPRETURN_REDEEMED,kmdtxid,komodoshis,kmdvout,opret,opretlen); - }*/ +/**** + * Roll backwards through the list of events, undoing them + * NOTE: The heart of this calls komodo_event_undo, which only lowers the sp->SAVEDHEIGHT + * @param sp the state + * @param symbol the symbol + * @param height the height + */ +void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -// process events -// +/** + * Set the SAVEDHEIGHT and CURRENT_HEIGHT if higher than what is in the state object + * @param sp the state + * @param kmdheight the desired kmdheight + * @param timestamp the timestamp + */ +void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp); -#endif +/**** + * Add a new height + * NOTE: If kmdheight is a negative number, it will cause a rewind event to abs(kmdheight) + * @param sp the state + * @param symbol the symbol + * @param height the height + * @param kmdheight the kmdheight to add + * @param timestamp the timestamp + */ +void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp); diff --git a/src/komodo_gateway.cpp b/src/komodo_gateway.cpp new file mode 100644 index 00000000000..0361443b895 --- /dev/null +++ b/src/komodo_gateway.cpp @@ -0,0 +1,2774 @@ + +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo.h" // for komodo_parsestatefile +#include "komodo_globals.h" + +#include "komodo_gateway.h" + +int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) +{ + int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed,maxval; + *available = *deposited = *issued = *withdrawn = *approved = *redeemed = 0; + if ( (baseid= komodo_baseid(base)) >= 0 ) + { + if ( (sp= komodo_stateptrget(base)) != 0 ) + { + *deposited = sp->deposited; + *issued = sp->issued; + *withdrawn = sp->withdrawn; + *approved = sp->approved; + *redeemed = sp->redeemed; + maxval = sp->approved; + if ( sp->withdrawn > maxval ) + maxval = sp->withdrawn; + netliability = (sp->issued - maxval) - sp->shorted; + maxallowed = komodo_maxallowed(baseid); + if ( netliability < maxallowed ) + *available = (maxallowed - netliability); + //printf("%llu - %llu %s %.8f %.8f %.8f %.8f %.8f\n",(long long)maxallowed,(long long)netliability,base,dstr(*deposited),dstr(*issued),dstr(*withdrawn),dstr(*approved),dstr(*redeemed)); + return(0); + } else printf("pax_fiatstatus cant get basesp.%s\n",base); + } // else printf("pax_fiatstatus illegal base.%s\n",base); + return(-1); +} + +void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type) +{ + memcpy(buf,&txid,32); + memcpy(&buf[32],&vout,2); + buf[34] = type; +} + +struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type) +{ + struct pax_transaction *pax; uint8_t buf[35]; + std::lock_guard lock(komodo_mutex); + pax_keyset(buf,txid,vout,type); + HASH_FIND(hh,PAX,buf,sizeof(buf),pax); + return(pax); +} + +struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout) +{ + struct pax_transaction *pax; int32_t i; uint8_t types[] = { 'I', 'D', 'X', 'A', 'W' }; + for (i=0; i lock(komodo_mutex); + pax_keyset(buf,txid,vout,type); + HASH_FIND(hh,PAX,buf,sizeof(buf),pax); + if ( pax == 0 ) + { + pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); + pax->txid = txid; + pax->vout = vout; + pax->type = type; + memcpy(pax->buf,buf,sizeof(pax->buf)); + HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); + //printf("ht.%d create pax.%p mark.%d\n",height,pax,mark); + } + if ( pax != 0 ) + { + pax->marked = mark; + //if ( height > 214700 || pax->height > 214700 ) + // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); + + } + return(pax); +} + +void komodo_paxdelete(struct pax_transaction *pax) +{ + return; // breaks when out of order + std::lock_guard lock(komodo_mutex); + HASH_DELETE(hh,PAX,pax); +} + +void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context +{ + struct pax_transaction *pax; uint8_t buf[35]; int32_t addflag = 0; struct komodo_state *sp; char str[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*s; + //if ( KOMODO_PAX == 0 ) + // return; + //if ( strcmp(symbol,ASSETCHAINS_SYMBOL) != 0 ) + // return; + sp = komodo_stateptr(str,dest); + { + std::lock_guard lock(komodo_mutex); + pax_keyset(buf,txid,vout,type); + HASH_FIND(hh,PAX,buf,sizeof(buf),pax); + if ( pax == 0 ) + { + pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); + pax->txid = txid; + pax->vout = vout; + pax->type = type; + memcpy(pax->buf,buf,sizeof(pax->buf)); + HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); + addflag = 1; + if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + { + int32_t i; for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&txid)[i]); + printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source); + } + } + } + if ( coinaddr != 0 ) + { + strcpy(pax->coinaddr,coinaddr); + if ( value != 0 ) + pax->komodoshis = value; + if ( symbol != 0 ) + strcpy(pax->symbol,symbol); + if ( source != 0 ) + strcpy(pax->source,source); + if ( fiatoshis != 0 ) + pax->fiatoshis = fiatoshis; + if ( rmd160 != 0 ) + memcpy(pax->rmd160,rmd160,20); + if ( height != 0 ) + pax->height = height; + if ( otherheight != 0 ) + pax->otherheight = otherheight; + } + else + { + pax->marked = height; + //printf("pax.%p MARK DEPOSIT ht.%d other.%d\n",pax,height,otherheight); + } +} + +int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax) +{ + int32_t i,len = 0; + if ( rwflag == 1 ) + { + for (i=0; i<32; i++) + opretbuf[len++] = ((uint8_t *)&pax->txid)[i]; + opretbuf[len++] = pax->vout & 0xff; + opretbuf[len++] = (pax->vout >> 8) & 0xff; + } + else + { + for (i=0; i<32; i++) + ((uint8_t *)&pax->txid)[i] = opretbuf[len++]; + //for (i=0; i<32; i++) + // printf("%02x",((uint8_t *)&pax->txid)[31-i]); + pax->vout = opretbuf[len++]; + pax->vout += ((uint32_t)opretbuf[len++] << 8); + //printf(" txid v.%d\n",pax->vout); + } + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis); + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis); + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height); + len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight); + if ( rwflag != 0 ) + { + memcpy(&opretbuf[len],pax->rmd160,20), len += 20; + for (i=0; i<4; i++) + opretbuf[len++] = pax->source[i]; + } + else + { + memcpy(pax->rmd160,&opretbuf[len],20), len += 20; + for (i=0; i<4; i++) + pax->source[i] = opretbuf[len++]; + } + return(len); +} + +int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo) +{ + struct pax_transaction p,*pax; int32_t i,n=0,j,len=0,incr,height,otherheight; uint8_t type,rmd160[20]; uint64_t fiatoshis; char symbol[KOMODO_ASSETCHAIN_MAXLEN]; + //if ( KOMODO_PAX == 0 ) + // return(0); + incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); + //41e77b91cb68dc2aa02fa88550eae6b6d44db676a7e935337b6d1392d9718f03cb0200305c90660400000000fbcbeb1f000000bde801006201000058e7945ad08ddba1eac9c9b6c8e1e97e8016a2d152 + + // 41e94d736ec69d88c08b5d238abeeca609c02357a8317e0d56c328bcb1c259be5d0200485bc80200000000404b4c000000000059470200b80b000061f22ba7d19fe29ac3baebd839af8b7127d1f9075553440046bb4cc7a3b5cd39dffe7206507a3482a00780e617f68b273cce9817ed69298d02001069ca1b0000000080f0fa02000000005b470200b90b000061f22ba7d19fe29ac3baebd839af8b7127d1f90755 + + //for (i=0; i>>>>>> %s: (%s) fiat %.8f kmdheight.%d other.%d -> %s %.8f\n",type=='A'?"approvedA":"issuedX",baseids[n]>=0?CURRENCIES[baseids[n]]:"???",dstr(p.fiatoshis),kmdheights[n],otherheights[n],coinaddr,dstr(values[n])); + } + } + } + else + { + for (i=0; i<4; i++) + base[i] = opretbuf[opretlen-4+i]; + for (j=0; j<32; j++) + { + ((uint8_t *)&txids[n])[j] = opretbuf[len++]; + //printf("%02x",((uint8_t *)&txids[n])[j]); + } + vouts[n] = opretbuf[len++]; + vouts[n] = (opretbuf[len++] << 8) | vouts[n]; + baseids[n] = komodo_baseid(base); + if ( (pax= komodo_paxfinds(txids[n],vouts[n])) != 0 ) + { + values[n] = (strcmp("KMD",base) == 0) ? pax->komodoshis : pax->fiatoshis; + srcvalues[n] = (strcmp("KMD",base) == 0) ? pax->fiatoshis : pax->komodoshis; + kmdheights[n] = pax->height; + otherheights[n] = pax->otherheight; + memcpy(&rmd160s[n * 20],pax->rmd160,20); + } + } + //printf(" komodo_issued_opreturn issuedtxid v%d i.%d opretlen.%d\n",vouts[n],n,opretlen); + } + } + return(n); +} + +int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed) +{ + int32_t ratio; + if ( seed == 0 && checkvalue != 0 ) + { + ratio = ((value << 6) / checkvalue); + if ( ratio >= 60 && ratio <= 67 ) + return(0); + else + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio); + return(-1); + } + } + else if ( checkvalue != 0 ) + { + ratio = ((value << 10) / checkvalue); + if ( ratio >= 1023 && ratio <= 1025 ) + return(0); + } + return(value != checkvalue); +} + +uint64_t komodo_paxtotal() +{ + struct pax_transaction *pax,*pax2,*tmp,*tmp2; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*str; int32_t i,ht; int64_t checktoshis; uint64_t seed,total = 0; struct komodo_state *basesp; + if ( KOMODO_PASSPORT_INITDONE == 0 ) //KOMODO_PAX == 0 || + return(0); + if ( komodo_isrealtime(&ht) == 0 ) + return(0); + else + { + HASH_ITER(hh,PAX,pax,tmp) + { + if ( pax->marked != 0 ) + continue; + if ( pax->type == 'A' || pax->type == 'D' || pax->type == 'X' ) + str = pax->symbol; + else str = pax->source; + basesp = komodo_stateptrget(str); + if ( basesp != 0 && pax->didstats == 0 ) + { + if ( pax->type == 'I' && (pax2= komodo_paxfind(pax->txid,pax->vout,'D')) != 0 ) + { + if ( pax2->fiatoshis != 0 ) + { + pax->komodoshis = pax2->komodoshis; + pax->fiatoshis = pax2->fiatoshis; + basesp->issued += pax->fiatoshis; + pax->didstats = 1; + if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p issued %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,str,dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight); + pax2->marked = pax->height; + pax->marked = pax->height; + } + } + else if ( pax->type == 'W' ) + { + //bitcoin_address(coinaddr,addrtype,rmd160,20); + if ( (checktoshis= komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis)) != 0 ) + { + if ( komodo_paxcmp(pax->source,pax->height,pax->komodoshis,checktoshis,seed) != 0 ) + { + pax->marked = pax->height; + //printf("WITHDRAW.%s mark <- %d %.8f != %.8f\n",pax->source,pax->height,dstr(checktoshis),dstr(pax->komodoshis)); + } + else if ( pax->validated == 0 ) + { + pax->validated = pax->komodoshis = checktoshis; + //int32_t j; for (j=0; j<32; j++) + // printf("%02x",((uint8_t *)&pax->txid)[j]); + //if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) + // printf(" v%d %p got WITHDRAW.%s kmd.%d ht.%d %.8f -> %.8f/%.8f\n",pax->vout,pax,pax->source,pax->height,pax->otherheight,dstr(pax->fiatoshis),dstr(pax->komodoshis),dstr(checktoshis)); + } + } + } + } + } + } + komodo_stateptr(symbol,dest); + HASH_ITER(hh,PAX,pax,tmp) + { + pax->ready = 0; + if ( 0 && pax->type == 'A' ) + printf("%p pax.%s <- %s marked.%d %.8f -> %.8f validated.%d approved.%d\n",pax,pax->symbol,pax->source,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0); + if ( pax->marked != 0 ) + continue; + if ( strcmp(symbol,pax->symbol) == 0 || pax->type == 'A' ) + { + if ( pax->marked == 0 ) + { + if ( komodo_is_issuer() != 0 ) + { + if ( pax->validated != 0 && pax->type == 'D' ) + { + total += pax->fiatoshis; + pax->ready = 1; + } + } + else if ( pax->approved != 0 && pax->type == 'A' ) + { + if ( pax->validated != 0 ) + { + total += pax->komodoshis; + pax->ready = 1; + } + else + { + seed = 0; + checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis); + //printf("paxtotal PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN); + //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight); + if ( seed != 0 && checktoshis != 0 ) + { + if ( checktoshis == pax->komodoshis ) + { + total += pax->komodoshis; + pax->validated = pax->komodoshis; + pax->ready = 1; + } else pax->marked = pax->height; + } + } + } + if ( 0 && pax->ready != 0 ) + printf("%p (%c) pax.%s marked.%d %.8f -> %.8f validated.%d approved.%d ready.%d ht.%d\n",pax,pax->type,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0,pax->ready,pax->height); + } + } + } + //printf("paxtotal %.8f\n",dstr(total)); + return(total); +} + +static int _paxorder(const void *a,const void *b) +{ +#define pax_a (*(struct pax_transaction **)a) +#define pax_b (*(struct pax_transaction **)b) + uint64_t aval,bval; + aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height; + bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height; + if ( bval > aval ) + return(-1); + else if ( bval < aval ) + return(1); + return(0); +#undef pax_a +#undef pax_b +} + +int32_t komodo_pending_withdraws(char *opretstr) // todo: enforce deterministic order +{ + struct pax_transaction *pax,*pax2,*tmp,*paxes[64]; uint8_t opretbuf[16384*4]; int32_t i,n,ht,len=0; uint64_t total = 0; + if ( KOMODO_PAX == 0 || KOMODO_PASSPORT_INITDONE == 0 ) + return(0); + if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) + return(0); + n = 0; + HASH_ITER(hh,PAX,pax,tmp) + { + if ( pax->type == 'W' ) + { + if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'A')) != 0 ) + { + if ( pax2->approved != 0 ) + pax->approved = pax2->approved; + } + else if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'X')) != 0 ) + pax->approved = pax->height; + //printf("pending_withdraw: pax %s marked.%u approved.%u validated.%llu\n",pax->symbol,pax->marked,pax->approved,(long long)pax->validated); + if ( pax->marked == 0 && pax->approved == 0 && pax->validated != 0 ) //strcmp((char *)"KMD",pax->symbol) == 0 && + { + if ( n < sizeof(paxes)/sizeof(*paxes) ) + { + paxes[n++] = pax; + //int32_t j; for (j=0; j<32; j++) + // printf("%02x",((uint8_t *)&pax->txid)[j]); + //printf(" %s.(kmdht.%d ht.%d marked.%u approved.%d validated %.8f) %.8f\n",pax->source,pax->height,pax->otherheight,pax->marked,pax->approved,dstr(pax->validated),dstr(pax->komodoshis)); + } + } + } + } + opretstr[0] = 0; + if ( n > 0 ) + { + opretbuf[len++] = 'A'; + qsort(paxes,n,sizeof(*paxes),_paxorder); + for (i=0; i>3)*7 ) + len += komodo_rwapproval(1,&opretbuf[len],paxes[i]); + } + if ( len > 0 ) + init_hexbytes_noT(opretstr,opretbuf,len); + } + //fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal())); + return(len); +} + +int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo) +{ + struct pax_transaction *pax,*tmp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint8_t *script,opcode,opret[16384*4],data[16384*4]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask,sum = 0; + if ( KOMODO_PASSPORT_INITDONE == 0 )//KOMODO_PAX == 0 || + return(0); + struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD"); + sp = komodo_stateptr(symbol,dest); + strcpy(symbol,base); + if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) + return(0); + PENDING_KOMODO_TX = 0; + for (i=0; i<3; i++) + { + if ( komodo_isrealtime(&ht) != 0 ) + break; + sleep(1); + } + if ( i == 3 ) + { + if ( tokomodo == 0 ) + printf("%s not realtime ht.%d\n",ASSETCHAINS_SYMBOL,ht); + return(0); + } + if ( tokomodo == 0 ) + { + opcode = 'I'; + } + else + { + opcode = 'X'; + if ( 1 || komodo_paxtotal() == 0 ) + return(0); + } + HASH_ITER(hh,PAX,pax,tmp) + { + if ( pax->type != 'D' && pax->type != 'A' ) + continue; + { +#ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE + if ( pax->height > 236000 ) + { + if ( kmdsp != 0 && kmdsp->NOTARIZED_HEIGHT >= pax->height ) + pax->validated = pax->komodoshis; + else if ( kmdsp->CURRENT_HEIGHT > pax->height+30 ) + pax->validated = pax->ready = 0; + } + else + { + if ( kmdsp != 0 && (kmdsp->NOTARIZED_HEIGHT >= pax->height || kmdsp->CURRENT_HEIGHT > pax->height+30) ) // assumes same chain as notarize + pax->validated = pax->komodoshis; + else pax->validated = pax->ready = 0; + } +#else + pax->validated = pax->komodoshis; +#endif + } + if ( ASSETCHAINS_SYMBOL[0] != 0 && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) ) + { + //if ( pax->height > 214700 || strcmp(ASSETCHAINS_SYMBOL,symbol) == 0 ) + // printf("miner.[%s]: skip %s %.8f when avail %.8f deposited %.8f, issued %.8f withdrawn %.8f approved %.8f redeemed %.8f\n",ASSETCHAINS_SYMBOL,symbol,dstr(pax->fiatoshis),dstr(available),dstr(deposited),dstr(issued),dstr(withdrawn),dstr(approved),dstr(redeemed)); + continue; + } + /*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0); + if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 ) + { + printf("reject 2\n"); + continue; + }*/ + if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 || pax->ready == 0) ) + { + if ( strcmp(pax->symbol,ASSETCHAINS_SYMBOL) == 0 ) + printf("pax->symbol.%s != %s or null pax->validated %.8f ready.%d ht.(%d %d)\n",pax->symbol,symbol,dstr(pax->validated),pax->ready,kmdsp->CURRENT_HEIGHT,pax->height); + pax->marked = pax->height; + continue; + } + if ( pax->ready == 0 ) + continue; + if ( pax->type == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( kmdsp != 0 ) + { + if ( (baseid= komodo_baseid(pax->symbol)) < 0 || ((1LL << baseid) & sp->RTmask) == 0 ) + { + printf("not RT for (%s) %llx baseid.%d %llx\n",pax->symbol,(long long)sp->RTmask,baseid,(long long)(1LL< %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); + if ( opcode == 'I' ) + { + sum += pax->fiatoshis; + if ( sum > available ) + break; + } + txNew->vout.resize(numvouts+1); + txNew->vout[numvouts].nValue = (opcode == 'I') ? pax->fiatoshis : pax->komodoshis; + txNew->vout[numvouts].scriptPubKey.resize(25); + script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; + *script++ = 0x76; + *script++ = 0xa9; + *script++ = 20; + memcpy(script,pax->rmd160,20), script += 20; + *script++ = 0x88; + *script++ = 0xac; + if ( tokomodo == 0 ) + { + for (i=0; i<32; i++) + data[len++] = ((uint8_t *)&pax->txid)[i]; + data[len++] = pax->vout & 0xff; + data[len++] = (pax->vout >> 8) & 0xff; + PENDING_KOMODO_TX += pax->fiatoshis; + } + else + { + len += komodo_rwapproval(1,&data[len],pax); + PENDING_KOMODO_TX += pax->komodoshis; + printf(" len.%d vout.%u DEPOSIT %.8f <- pax.%s pending ht %d %d %.8f | ",len,pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,pax->height,pax->otherheight,dstr(PENDING_KOMODO_TX)); + } + if ( numvouts++ >= 64 || sum > COIN ) + break; + } + if ( numvouts > 1 ) + { + if ( tokomodo != 0 ) + strcpy(symbol,(char *)"KMD"); + for (i=0; symbol[i]!=0; i++) + data[len++] = symbol[i]; + data[len++] = 0; + for (i=0; ivout.resize(numvouts+1); + txNew->vout[numvouts].nValue = 0; + txNew->vout[numvouts].scriptPubKey.resize(opretlen); + script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; + memcpy(script,opret,opretlen); + for (i=0; i<8; i++) + printf("%02x",opret[i]); + printf(" <- opret, MINER deposits.%d (%s) vouts.%d %.8f opretlen.%d\n",tokomodo,ASSETCHAINS_SYMBOL,numvouts,dstr(PENDING_KOMODO_TX),opretlen); + return(1); + } + return(0); +} + +const char *banned_txids[] = +{ + "78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", // vout1 only 233559 + "00697be658e05561febdee1aafe368b821ca33fbb89b7027365e3d77b5dfede5", //234172 + "e909465788b32047c472d73e882d79a92b0d550f90be008f76e1edaee6d742ea", //234187 + "f56c6873748a327d0b92b8108f8ec8505a2843a541b1926022883678fb24f9dc", //234188 + "abf08be07d8f5b3a433ddcca7ef539e79a3571632efd6d0294ec0492442a0204", //234213 + "3b854b996cc982fba8c06e76cf507ae7eed52ab92663f4c0d7d10b3ed879c3b0", //234367 + "fa9e474c2cda3cb4127881a40eb3f682feaba3f3328307d518589024a6032cc4", //234635 + "ca746fa13e0113c4c0969937ea2c66de036d20274efad4ce114f6b699f1bc0f3", //234662 + "43ce88438de4973f21b1388ffe66e68fda592da38c6ef939be10bb1b86387041", //234697 + "0aeb748de82f209cd5ff7d3a06f65543904c4c17387c9d87c65fd44b14ad8f8c", //234899 + "bbd3a3d9b14730991e1066bd7c626ca270acac4127131afe25f877a5a886eb25", //235252 + "fa9943525f2e6c32cbc243294b08187e314d83a2870830180380c3c12a9fd33c", //235253 + "a01671c8775328a41304e31a6693bbd35e9acbab28ab117f729eaba9cb769461", //235265 + "2ef49d2d27946ad7c5d5e4ab5c089696762ff04e855f8ab48e83bdf0cc68726d", //235295 + "c85dcffb16d5a45bd239021ad33443414d60224760f11d535ae2063e5709efee", //235296 + // all vouts banned + "c4ea1462c207547cd6fb6a4155ca6d042b22170d29801a465db5c09fec55b19d", //246748 + "305dc96d8bc23a69d3db955e03a6a87c1832673470c32fe25473a46cc473c7d1", //247204 + //"43416a0c4da6b1a5c1d375bdbe8f7dc8d44d8f60df593d3376aa8221ec66357e", // vout0 only + //"1eb295ed54c47f35cbccd7e7e40d03041f1853581da6d41102a9d8813782b6cb", + //"db121e4012222adfc841824984a2a90b7e5b018dd71307822537d58160195e43", + //"28f95b8148ac4ae6e09c7380e34422fab41d568a411e53dc94823e36a3d6f386", + //"01d8c839463bda2f2f6400ede4611357913684927a767422a8560ead1b22557c", + //"6e4980a9e1bd669f4df04732dc6f11b7773b6de88d1abcf89a6b9007d72ef9ac", + //"6cc1d0495170bc0e11fd3925297623562e529ea1336b66ea61f8a1159041aed2", + //"250875424cece9bcd98cb226b09da7671625633d6958589e3a462bad89ad87cc", // missed + //"ea8659011de52f4dac42cda12326064b7b5013b8492f88e33159884ca299aa05", // missed + //"ce567928b5490a17244167af161b1d8dd6ff753fef222fe6855d95b2278a35b3", // missed +}; + +int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts) +{ + if ( k < indallvouts ) + return(vout == 1); + else if ( k == indallvouts || k == indallvouts+1 ) + return(1); + else return(vout == 0); +} + +int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) +{ + int32_t i; + if ( sizeof(banned_txids)/sizeof(*banned_txids) > max ) + { + fprintf(stderr,"komodo_bannedset: buffer too small %d vs %d\n",(int32_t)(sizeof(banned_txids)/sizeof(*banned_txids)),max); + StartShutdown(); + } + for (i=0; i 1 && block.vtx[txn_count-1].vout.size() > 0 && block.vtx[txn_count-1].vout[0].nValue == 5000 ) + { + /* + if ( block.vtx[txn_count-1].vin.size() == 1 && GetTransaction(block.vtx[txn_count-1].vin[0].prevout.hash,tx,hash,false) && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) + notmatched = 1; + */ + if ( block.vtx[txn_count-1].vin.size() == 1 ) { + uint256 hashNotaryProofVin = block.vtx[txn_count-1].vin[0].prevout.hash; + int fNotaryProofVinTxFound = GetTransaction(hashNotaryProofVin,tx,hash,false); + if (!fNotaryProofVinTxFound) { + // try to search in the same block + BOOST_FOREACH(const CTransaction &txInThisBlock, block.vtx) { + if (txInThisBlock.GetHash() == hashNotaryProofVin) { + fNotaryProofVinTxFound = 1; + tx = txInThisBlock; + hash = block.GetHash(); + break; + } + } + } + if ( fNotaryProofVinTxFound && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) + { + notmatched = 1; + } + } + } + n = block.vtx[i].vin.size(); + for (j=0; j= indallvouts) ) + { + printf("banned tx.%d being used at ht.%d txi.%d vini.%d\n",k,height,i,j); + return(-1); + } + } + } + } + } + // we don't want these checks in VRSC, leave it at the Sapling upgrade + if ( ASSETCHAINS_SYMBOL[0] == 0 || + ((ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1) || + NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING) ) + { + n = block.vtx[0].vout.size(); + int64_t val,prevtotal = 0; int32_t strangeout=0,overflow = 0; + total = 0; + for (i=1; i= MAX_MONEY ) + { + overflow = 1; + break; + } + if ( i > 1 && script[0] != 0x6a && val < 5000 ) + strangeout++; + total += val; + if ( total < prevtotal || (val != 0 && total == prevtotal) ) + { + overflow = 1; + break; + } + prevtotal = total; + } + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + if ( overflow != 0 || total > COIN/10 ) + { + if ( height >= activation ) + { + if ( height > 800000 ) + fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n); + return(-1); + } + } + else if ( block.nBits == KOMODO_MINDIFF_NBITS && total > 0 ) // to deal with fee stealing + { + fprintf(stderr,"notary mined ht.%d with extra %.8f\n",height,dstr(total)); + if ( height > KOMODO_NOTARIES_HEIGHT1 ) + return(-1); + } + if ( strangeout != 0 || notmatched != 0 ) + { + if ( 0 && strcmp(NOTARY_PUBKEY.c_str(),"03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828") == 0 ) + fprintf(stderr,">>>>>>>>>>>>> DUST ht.%d strangout.%d notmatched.%d <<<<<<<<<\n",height,strangeout,notmatched); + if ( height > 1000000 && strangeout != 0 ) + return(-1); + } + else if ( height > 814000 ) + { + script = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; + //int32_t notary = komodo_electednotary(&num,script+1,height,0); + //if ( (-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)) < 0 ) + // fprintf(stderr, ">>>>>>> FAILED BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); + //else + // fprintf(stderr, "<<<<<<< VALID BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); + return(-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)); + } + } + else + { + checktoshis = 0; + if ( (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1 ) + { + if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 ) + { + fprintf(stderr,"ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); + return(-1); + } + } + if ( height > 1 && checktoshis == 0 ) + { + checktoshis = ((uint64_t)GetBlockSubsidy(height, Params().GetConsensus()) - block.vtx[0].vout[0].nValue); + // some pools will need to change their pool fee to be (poolfee % - txfees) + //checktoshis += txn_count * 0.001; // rely on higher level validations to prevent emitting more coins than actual txfees + } + if ( height >= 2 && (overflow != 0 || total > checktoshis || strangeout != 0) ) + { + fprintf(stderr,"checkdeposit: ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); + if ( strangeout != 0 ) + fprintf(stderr,">>>>>>>>>>>>> %s DUST ht.%d strangeout.%d notmatched.%d <<<<<<<<<\n",ASSETCHAINS_SYMBOL,height,strangeout,notmatched); + return(-1); + } + } + } + return(0); +} + +/*** + * handle an opreturn + * @param height the height + * @param value the value + * @param opretbuf the buffer + * @param opretlen the length of the buffer + * @param txid + * @param vout + * @param source + * @returns result (i.e. "unknown", "assetchain", "kv", ect. + */ +const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) +{ + uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; + const char *typestr = "unknown"; + if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' ) + { + //printf("komodo_opreturn skip %s\n",ASSETCHAINS_SYMBOL); + return("assetchain"); + } + memset(baseids,0xff,sizeof(baseids)); + memset(values,0,sizeof(values)); + memset(srcvalues,0,sizeof(srcvalues)); + memset(rmd160s,0,sizeof(rmd160s)); + memset(kmdheights,0,sizeof(kmdheights)); + memset(otherheights,0,sizeof(otherheights)); + tokomodo = (komodo_is_issuer() == 0); + if ( opretbuf[0] == 'K' && opretlen != 40 ) + { + komodo_kvupdate(opretbuf,opretlen,value); + return("kv"); + } + else if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_PAX == 0 ) + return("nopax"); + if ( opretbuf[0] == 'D' ) + { + tokomodo = 0; + if ( opretlen == 38 ) // any KMD tx + { + iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); + memset(base,0,sizeof(base)); + PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&fiatoshis); + bitcoin_address(coinaddr,addrtype,rmd160,20); + checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,fiatoshis); + if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) != 0 ) + checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,height,base,fiatoshis); + typestr = "deposit"; + if ( 0 && strcmp("NOK",base) == 0 ) + { + printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); + printf("(%s) (%s) kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&txid)[i]); + printf(" <- txid.v%u ",vout); + for (i=0; i<33; i++) + printf("%02x",pubkey33[i]); + printf(" checkpubkey check %.8f v %.8f dest.(%s) kmdheight.%d height.%d\n",dstr(checktoshis),dstr(value),destaddr,kmdheight,height); + } + if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 && (kmdheight > 195000 || kmdheight <= height) ) + { + didstats = 0; + if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) == 0 ) + { + if ( (pax= komodo_paxfind(txid,vout,'D')) == 0 ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->deposited += fiatoshis; + didstats = 1; + if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p deposited %s += %.8f kmdheight.%d %.8f\n",basesp,base,dstr(fiatoshis),kmdheight,dstr(value)); + } else printf("cant get stateptr.(%s)\n",base); + komodo_gateway_deposit(coinaddr,value,base,fiatoshis,rmd160,txid,vout,'D',kmdheight,height,(char *)"KMD",0); + } + if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) + { + pax->height = kmdheight; + pax->validated = value; + pax->komodoshis = value; + pax->fiatoshis = fiatoshis; + if ( didstats == 0 && pax->didstats == 0 ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->deposited += fiatoshis; + didstats = 1; + if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p depositedB %s += %.8f/%.8f kmdheight.%d/%d %.8f/%.8f\n",basesp,base,dstr(fiatoshis),dstr(pax->fiatoshis),kmdheight,pax->height,dstr(value),dstr(pax->komodoshis)); + } + } // + if ( didstats != 0 ) + pax->didstats = 1; + if ( (pax2= komodo_paxfind(txid,vout,'I')) != 0 ) + { + pax2->fiatoshis = pax->fiatoshis; + pax2->komodoshis = pax->komodoshis; + pax->marked = pax2->marked = pax->height; + pax2->height = pax->height = height; + if ( pax2->didstats == 0 ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->issued += pax2->fiatoshis; + pax2->didstats = 1; + if ( 0 && strcmp(base,"USD") == 0 ) + printf("########### %p issueda %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,base,dstr(pax2->fiatoshis),pax2->height,dstr(pax2->komodoshis),pax2->otherheight,height); + } + } + } + } + } + else + { + if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) + pax->marked = checktoshis; + if ( kmdheight > 238000 && (kmdheight > 214700 || strcmp(base,ASSETCHAINS_SYMBOL) == 0) ) //seed != 0 && + printf("pax %s deposit %.8f rejected kmdheight.%d %.8f KMD check %.8f seed.%llu\n",base,dstr(fiatoshis),kmdheight,dstr(value),dstr(checktoshis),(long long)seed); + } + } //else printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); + } //else printf("unsupported size.%d for opreturn D\n",opretlen); + } + else if ( opretbuf[0] == 'I' ) + { + tokomodo = 0; + if ( strncmp((char *)"KMD",(char *)&opretbuf[opretlen-4],3) != 0 && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 ) + { + if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,0)) > 0 ) + { + for (i=0; itype = opretbuf[0]; + strcpy(pax->source,(char *)&opretbuf[opretlen-4]); + if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 && pax2->fiatoshis != 0 && pax2->komodoshis != 0 ) + { + // realtime path? + pax->fiatoshis = pax2->fiatoshis; + pax->komodoshis = pax2->komodoshis; + pax->marked = pax2->marked = pax2->height; + if ( pax->didstats == 0 ) + { + if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->issued += pax->fiatoshis; + pax->didstats = 1; + pax->height = pax2->height; + pax->otherheight = height; + if ( 1 && strcmp(CURRENCIES[baseids[i]],"USD") == 0 ) + printf("########### %p issuedb %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,CURRENCIES[baseids[i]],dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight,height); + } + } + } + } + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'I',height)) != 0 ) + komodo_paxdelete(pax); + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'D',height)) != 0 ) + komodo_paxdelete(pax); + } + } //else printf("opreturn none issued?\n"); + } + } + else if ( height < 236000 && opretbuf[0] == 'W' && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 )//&& opretlen >= 38 ) + { + if ( komodo_baseid((char *)&opretbuf[opretlen-4]) >= 0 && strcmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4]) == 0 ) + { + for (i=0; i (%s) len.%d\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr,opretlen); + didstats = 0; + //if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 ) + { + if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) ) + { + if ( (basesp= komodo_stateptrget(base)) != 0 ) + { + basesp->withdrawn += value; + didstats = 1; + if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) + printf("########### %p withdrawn %s += %.8f check %.8f\n",basesp,base,dstr(value),dstr(checktoshis)); + } + if ( 0 && strcmp(base,"RUB") == 0 && (pax == 0 || pax->approved == 0) ) + printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height); + } + komodo_gateway_deposit(coinaddr,0,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0); + if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 ) + { + pax->type = opretbuf[0]; + strcpy(pax->source,base); + strcpy(pax->symbol,"KMD"); + pax->height = kmdheight; + pax->otherheight = height; + pax->komodoshis = komodoshis; + } + } // else printf("withdraw %s paxcmp ht.%d %d error value %.8f -> %.8f vs %.8f\n",base,kmdheight,height,dstr(value),dstr(komodoshis),dstr(checktoshis)); + // need to allocate pax + } + else if ( height < 236000 && tokomodo != 0 && opretbuf[0] == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) + { + tokomodo = 1; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + { + for (i=0; i 0 ) + { + for (i=0; isymbol); + printf("override neg1 with (%s)\n",pax->symbol); + } + if ( baseids[i] < 0 ) + continue; + } + didstats = 0; + seed = 0; + checktoshis = komodo_paxprice(&seed,kmdheights[i],CURRENCIES[baseids[i]],(char *)"KMD",(uint64_t)values[i]); + //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)values[i]/COIN,(double)srcvalues[i]/COIN,(double)checktoshis/COIN); + if ( srcvalues[i] == checktoshis ) + { + if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) + { + bitcoin_address(coinaddr,60,&rmd160s[i*20],20); + komodo_gateway_deposit(coinaddr,srcvalues[i],CURRENCIES[baseids[i]],values[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]); + if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) + printf("unexpected null pax for approve\n"); + else pax->validated = checktoshis; + if ( (pax2= komodo_paxfind(txids[i],vouts[i],'W')) != 0 ) + pax2->approved = kmdheights[i]; + komodo_paxmark(height,txids[i],vouts[i],'W',height); + //komodo_paxmark(height,txids[i],vouts[i],'A',height); + if ( values[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->approved += values[i]; + didstats = 1; + //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); + } + //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i])); + } + else if ( pax->didstats == 0 && srcvalues[i] != 0 ) + { + if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->approved += values[i]; + didstats = 1; + //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); + } + } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]); + if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 ) + { + pax->type = opretbuf[0]; + pax->approved = kmdheights[i]; + pax->validated = checktoshis; + if ( didstats != 0 ) + pax->didstats = 1; + //if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) + //printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax); + } + } + } + } //else printf("n.%d from opreturns\n",n); + //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal())); + } + else if ( height < 236000 && opretbuf[0] == 'X' && ASSETCHAINS_SYMBOL[0] == 0 ) + { + tokomodo = 1; + if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,1)) > 0 ) + { + for (i=0; itype = opretbuf[0]; + if ( height < 121842 ) // fields got switched around due to legacy issues and approves + value = srcvalues[i]; + else value = values[i]; + if ( baseids[i] >= 0 && value != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) + { + basesp->redeemed += value; + pax->didstats = 1; + if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) + printf("ht.%d %.8f ########### %p redeemed %s += %.8f %.8f kht.%d ht.%d\n",height,dstr(value),basesp,CURRENCIES[baseids[i]],dstr(value),dstr(srcvalues[i]),kmdheights[i],otherheights[i]); + } + } + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'W',height)) != 0 ) + komodo_paxdelete(pax); + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'A',height)) != 0 ) + komodo_paxdelete(pax); + if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'X',height)) != 0 ) + komodo_paxdelete(pax); + } + } //else printf("komodo_issued_opreturn returned %d\n",n); + } + return(typestr); +} + +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); + +void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest) +{ + uint8_t func; long lastK,lastT,lastN,lastV,fpos,lastfpos; int32_t i,count,doissue,iter,numn,numv,numN,numV,numR; uint32_t tmp,prevpos100,offset; + count = numR = numN = numV = numn = numv = 0; + lastK = lastT = lastN = lastV = -1; + for (iter=0; iter<2; iter++) + { + for (lastfpos=fpos=prevpos100=i=0; i> 8); + fpos = prevpos100 + offset; + if ( lastfpos >= datalen || (filedata[lastfpos] != func && func != 0) ) + printf("i.%d/n.%d lastfpos.%ld >= datalen.%ld or [%d] != func.%d\n",i,n,lastfpos,datalen,filedata[lastfpos],func); + else if ( iter == 0 ) + { + switch ( func ) + { + default: case 'P': case 'U': case 'D': + inds[i] &= 0xffffff00; + break; + case 'K': + lastK = lastfpos; + inds[i] &= 0xffffff00; + break; + case 'T': + lastT = lastfpos; + inds[i] &= 0xffffff00; + break; + case 'N': + lastN = lastfpos; + numN++; + break; + case 'V': + lastV = lastfpos; + numV++; + break; + case 'R': + numR++; + break; + } + } + else + { + doissue = 0; + if ( func == 'K' ) + { + if ( lastK == lastfpos ) + doissue = 1; + } + else if ( func == 'T' ) + { + if ( lastT == lastfpos ) + doissue = 1; + } + else if ( func == 'N' ) + { + if ( numn > numN-128 ) + doissue = 1; + numn++; + } + else if ( func == 'V' ) + { + if ( KOMODO_PAX != 0 && numv > numV-1440 ) + doissue = 1; + numv++; + } + else if ( func == 'R' ) + doissue = 1; + if ( doissue != 0 ) + { + //printf("issue %c total.%d lastfpos.%ld\n",func,count,lastfpos); + komodo_parsestatefiledata(sp,filedata,&lastfpos,datalen,symbol,dest); + count++; + } + } + } + lastfpos = fpos; + } + } + printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); + /*else if ( func == 'K' ) // KMD height: stop after 1st + else if ( func == 'T' ) // KMD height+timestamp: stop after 1st + else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; + else if ( func == 'V' ) // price feed: can stop after 1440+ + else if ( func == 'R' ) // opreturn:*/ +} + +/**** + * Load file contents into buffer + * @param fname the filename + * @param bufp the buffer that will contain the file contents + * @param lenp the length of the file + * @param allocsizep the buffer size allocated + * @returns the file contents + */ +void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) +{ + FILE *fp; + long filesize,buflen = *allocsizep; + uint8_t *buf = *bufp; + *lenp = 0; + if ( (fp= fopen(fname,"rb")) != 0 ) + { + fseek(fp,0,SEEK_END); + filesize = ftell(fp); + if ( filesize == 0 ) + { + fclose(fp); + *lenp = 0; + //printf("OS_loadfile null size.(%s)\n",fname); + return(0); + } + if ( filesize > buflen ) + { + *allocsizep = filesize; + *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); + } + rewind(fp); + if ( buf == 0 ) + printf("Null buf ???\n"); + else + { + if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) + printf("error reading filesize.%ld\n",(long)filesize); + buf[filesize] = 0; + } + fclose(fp); + *lenp = filesize; + //printf("loaded.(%s)\n",buf); + } //else printf("OS_loadfile couldnt load.(%s)\n",fname); + return(buf); +} + +/*** + * Get file contents + * @param allocsizep the size allocated for the file contents (NOTE: this will probably be 64 bytes larger than the file size) + * @param fname the file name + * @returns the data from the file + */ +uint8_t *OS_fileptr(long *allocsizep,char *fname) +{ + long filesize = 0; // the size of the file + uint8_t *buf = 0; // a pointer to the buffer + void *retptr; // the return pointer (points to buf) + *allocsizep = 0; + retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); + return((uint8_t *)retptr); +} + +long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest) +{ + FILE *fp; long fsize,lastfpos=0,fpos=0; uint8_t *inds,func; int32_t i,n; uint32_t offset,tmp,prevpos100 = 0; + *indcounterp = *prevpos100p = 0; + if ( (inds= OS_fileptr(&fsize,indfname)) != 0 ) + { + lastfpos = 0; + fprintf(stderr,"inds.%p validate %s fsize.%ld datalen.%ld n.%d lastfpos.%ld\n",inds,indfname,fsize,datalen,(int32_t)(fsize / sizeof(uint32_t)),lastfpos); + if ( (fsize % sizeof(uint32_t)) == 0 ) + { + n = (int32_t)(fsize / sizeof(uint32_t)); + for (i=0; i n-10 ) + printf("%d: tmp.%08x [%c] prevpos100.%u\n",i,tmp,tmp&0xff,prevpos100); + if ( (i % 100) == 0 ) + prevpos100 = tmp; + else + { + func = (tmp & 0xff); + offset = (tmp >> 8); + fpos = prevpos100 + offset; + if ( lastfpos >= datalen || filedata[lastfpos] != func ) + { + printf("validate.%d error (%u %d) prev100 %u -> fpos.%ld datalen.%ld [%d] (%c) vs (%c) lastfpos.%ld\n",i,offset,func,prevpos100,fpos,datalen,lastfpos < datalen ? filedata[lastfpos] : -1,func,filedata[lastfpos],lastfpos); + return(-1); + } + } + lastfpos = fpos; + } + *indcounterp = n; + *prevpos100p = prevpos100; + if ( sp != 0 ) + komodo_stateind_set(sp,(uint32_t *)inds,n,filedata,fpos,symbol,dest); + //printf("free inds.%p %s validated[%d] fpos.%ld datalen.%ld, offset %ld vs fsize.%ld\n",inds,indfname,i,fpos,datalen,i * sizeof(uint32_t),fsize); + free(inds); + return(fpos); + } else printf("wrong filesize %s %ld\n",indfname,fsize); + } + free(inds); + fprintf(stderr,"indvalidate return -1\n"); + return(-1); +} + +long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp) +{ + uint32_t tmp; + if ( indfp != 0 ) + { + tmp = ((uint32_t)(newfpos - *prevpos100p) << 8) | (func & 0xff); + if ( ftell(indfp)/sizeof(uint32_t) != *indcounterp ) + printf("indfp fpos %ld -> ind.%ld vs counter.%u\n",ftell(indfp),ftell(indfp)/sizeof(uint32_t),*indcounterp); + //fprintf(stderr,"ftell.%ld indcounter.%u lastfpos.%ld newfpos.%ld func.%02x\n",ftell(indfp),*indcounterp,lastfpos,newfpos,func); + fwrite(&tmp,1,sizeof(tmp),indfp), (*indcounterp)++; + if ( (*indcounterp % 100) == 0 ) + { + *prevpos100p = (uint32_t)newfpos; + fwrite(prevpos100p,1,sizeof(*prevpos100p),indfp), (*indcounterp)++; + } + } + return(newfpos); +} + +/*** + * Initialize state from the filesystem + * @param sp the state to initialize + * @param fname the filename + * @param symbol + * @param dest + * @returns -1 on error, 1 on success + */ +int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest) +{ + FILE *indfp; // an index file that will be created + char indfname[1024]; // the filename of the index file + uint8_t *filedata; // data read from the file fname + long validated=-1; // not used + long datalen; // length of the data read from fname plus a little more + long fpos; // where we are reading in filedata + long lastfpos; // not used + uint32_t tmp; // not used + uint32_t prevpos100; // position to be written in index file + uint32_t indcounter; // position within index file + uint32_t starttime = (uint32_t)time(NULL); + int32_t func; // record type + int32_t finished = 0; // boolean, true if file has been read successfully + + safecopy(indfname,fname,sizeof(indfname)-4); // truncate 4 characters from filename + strcat(indfname,".ind"); + + if ( (filedata= OS_fileptr(&datalen,fname)) != 0 ) + { + if ( 1 )//datalen >= (1LL << 32) || GetArg("-genind",0) != 0 || (validated= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) + { + lastfpos = fpos = 0; + indcounter = prevpos100 = 0; + if ( (indfp= fopen(indfname,"wb")) != 0 ) + fwrite(&prevpos100,1,sizeof(prevpos100),indfp), indcounter++; + fprintf(stderr,"processing %s %ldKB, validated.%ld\n",fname,datalen/1024,validated); + while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) + { + lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); + } + if ( indfp != 0 ) + { + fclose(indfp); + if ( (fpos= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) + printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); + else printf("%s validated fpos.%ld\n",indfname,fpos); + } + finished = 1; + fprintf(stderr,"took %d seconds to process %s %ldKB\n",(int32_t)(time(NULL)-starttime),fname,datalen/1024); + } + else if ( validated > 0 ) + { + if ( (indfp= fopen(indfname,"rb+")) != 0 ) + { + lastfpos = fpos = validated; + fprintf(stderr,"datalen.%ld validated %ld -> indcounter %u, prevpos100 %u offset.%d\n",datalen,validated,indcounter,prevpos100,(int32_t)(indcounter * sizeof(uint32_t))); + if ( fpos < datalen ) + { + fseek(indfp,indcounter * sizeof(uint32_t),SEEK_SET); + if ( ftell(indfp) == indcounter * sizeof(uint32_t) ) + { + while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) + { + lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); + if ( lastfpos != fpos ) + fprintf(stderr,"unexpected lastfpos.%ld != %ld\n",lastfpos,fpos); + } + } + fclose(indfp); + } + if ( komodo_stateind_validate(sp,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest) < 0 ) + printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); + else + { + printf("%s validated updated from validated.%ld to %ld new.[%ld] -> indcounter %u, prevpos100 %u offset.%ld | elapsed %d seconds\n",indfname,validated,fpos,fpos-validated,indcounter,prevpos100,indcounter * sizeof(uint32_t),(int32_t)(time(NULL) - starttime)); + finished = 1; + } + } + } else printf("komodo_faststateinit unexpected case\n"); + free(filedata); + return(finished == 1); + } + return(-1); +} + +uint64_t komodo_interestsum(); + +void komodo_passport_iteration() +{ + static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; + int32_t maxseconds = 10; + FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; uint64_t RTmask = 0; //CBlockIndex *pindex; + expired = 0; + while ( 0 && KOMODO_INITDONE == 0 ) + { + fprintf(stderr,"[%s] PASSPORT iteration waiting for KOMODO_INITDONE\n",ASSETCHAINS_SYMBOL); + sleep(3); + } + if ( komodo_chainactive_timestamp() > lastinterest ) + { + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + komodo_interestsum(); + //komodo_longestchain(); + lastinterest = komodo_chainactive_timestamp(); + } + refsp = komodo_stateptr(symbol,dest); + if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDCC") == 0 ) + { + refid = 33; + limit = 10000000; + jumblr_iteration(); + } + else + { + limit = 10000000; + refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 + if ( refid == 0 ) + { + KOMODO_PASSPORT_INITDONE = 1; + return; + } + } + /*if ( KOMODO_PAX == 0 ) + { + KOMODO_PASSPORT_INITDONE = 1; + return; + }*/ + starttime = (uint32_t)time(NULL); + if ( callcounter++ < 1 ) + limit = 10000; + lasttime = starttime; + for (baseid=32; baseid>=0; baseid--) + { + if ( time(NULL) >= starttime+maxseconds ) + break; + sp = 0; + isrealtime = 0; + base = (char *)CURRENCIES[baseid]; + //printf("PASSPORT %s baseid+1 %d refid.%d\n",ASSETCHAINS_SYMBOL,baseid+1,refid); + if ( baseid+1 != refid ) // only need to import state from a different coin + { + if ( baseid == 32 ) // only care about KMD's state + { + refsp->RTmask &= ~(1LL << baseid); + komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate"); + komodo_nameset(symbol,dest,base); + sp = komodo_stateptrget(symbol); + n = 0; + if ( lastpos[baseid] == 0 && (filedata= OS_fileptr(&datalen,fname)) != 0 ) + { + fpos = 0; + fprintf(stderr,"%s processing %s %ldKB\n",ASSETCHAINS_SYMBOL,fname,datalen/1024); + while ( komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest) >= 0 ) + lastfpos = fpos; + fprintf(stderr,"%s took %d seconds to process %s %ldKB\n",ASSETCHAINS_SYMBOL,(int32_t)(time(NULL)-starttime),fname,datalen/1024); + lastpos[baseid] = lastfpos; + free(filedata), filedata = 0; + datalen = 0; + } + else if ( (fp= fopen(fname,"rb")) != 0 && sp != 0 ) + { + fseek(fp,0,SEEK_END); + //fprintf(stderr,"couldnt OS_fileptr(%s), freading %ldKB\n",fname,ftell(fp)/1024); + if ( ftell(fp) > lastpos[baseid] ) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("%s passport refid.%d %s fname.(%s) base.%s %ld %ld\n",ASSETCHAINS_SYMBOL,refid,symbol,fname,base,ftell(fp),lastpos[baseid]); + fseek(fp,lastpos[baseid],SEEK_SET); + while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 && n < limit ) + { + if ( n == limit-1 ) + { + if ( time(NULL) < starttime+maxseconds ) + n = 0; + else + { + //printf("expire passport loop %s -> %s at %ld\n",ASSETCHAINS_SYMBOL,base,lastpos[baseid]); + expired++; + } + } + n++; + } + lastpos[baseid] = ftell(fp); + if ( 0 && lastpos[baseid] == 0 && strcmp(symbol,"KMD") == 0 ) + printf("from.(%s) lastpos[%s] %ld isrt.%d\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid],komodo_isrealtime(&ht)); + } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp)); + fclose(fp); + } else fprintf(stderr,"load error.(%s) %p\n",fname,sp); + komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); + if ( (fp= fopen(fname,"rb")) != 0 ) + { + if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) ) + { + sp->CURRENT_HEIGHT = buf[0]; + if ( buf[0] != 0 && buf[0] >= buf[1] && buf[2] > time(NULL)-60 ) + { + isrealtime = 1; + RTmask |= (1LL << baseid); + memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); + } + else if ( KOMODO_PAX != 0 && (time(NULL)-buf[2]) > 60 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"[%s]: %s not RT %u %u %d\n",ASSETCHAINS_SYMBOL,base,buf[0],buf[1],(int32_t)(time(NULL)-buf[2])); + } //else fprintf(stderr,"%s size error RT\n",base); + fclose(fp); + } //else fprintf(stderr,"%s open error RT\n",base); + } + } + else + { + refsp->RTmask &= ~(1LL << baseid); + komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + buf[0] = (uint32_t)chainActive.LastTip()->GetHeight(); + buf[1] = (uint32_t)komodo_longestchain(); + if ( buf[0] != 0 && buf[0] == buf[1] ) + { + buf[2] = (uint32_t)time(NULL); + RTmask |= (1LL << baseid); + memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); + if ( refid != 0 ) + memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0])); + } + if ( fwrite(buf,1,sizeof(buf),fp) != sizeof(buf) ) + fprintf(stderr,"[%s] %s error writing realtime\n",ASSETCHAINS_SYMBOL,base); + fclose(fp); + } else fprintf(stderr,"%s create error RT\n",base); + } + if ( sp != 0 && isrealtime == 0 ) + refsp->RTbufs[0][2] = 0; + } + //komodo_paxtotal(); // calls komodo_isrealtime(), which calls komodo_longestchain() + refsp->RTmask |= RTmask; + if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 ) + { + KOMODO_PASSPORT_INITDONE = 1; + printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); + } +} + + +extern std::vector Mineropret; // opreturn data set by the data gathering code +#define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% +#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR +#define KOMODO_LOCALPRICE_CACHESIZE 13 +#define KOMODO_MAXPRICES 2048 +#define PRICES_SMOOTHWIDTH 1 + +#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) + +/* +const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) +// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" +const char *Forex[] = +{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" +}; // must be in ECB list +*/ + +struct komodo_extremeprice +{ + uint256 blockhash; + uint32_t pricebits,timestamp; + int32_t height; + int16_t dir,ind; +} ExtremePrice; + +struct komodo_priceinfo +{ + FILE *fp; + char symbol[PRICES_MAXNAMELENGTH]; // TODO: it was 64 +} PRICES[KOMODO_MAXPRICES]; + +uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; +int64_t PriceMult[KOMODO_MAXPRICES]; +int32_t komodo_cbopretsize(uint64_t flags); + +void komodo_PriceCache_shift() +{ + int32_t i; + for (i=KOMODO_LOCALPRICE_CACHESIZE-1; i>0; i--) + memcpy(PriceCache[i],PriceCache[i-1],sizeof(PriceCache[i])); + memcpy(PriceCache[0],Mineropret.data(),Mineropret.size()); +} + +int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block) +{ + CTransaction tx; int32_t numvouts; std::vector vopret; + tx = block->vtx[0]; + numvouts = (int32_t)tx.vout.size(); + GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); + if ( vopret.size() >= PRICES_SIZEBIT0 ) + { + if ( seedp != 0 ) + memcpy(seedp,&block->hashMerkleRoot,sizeof(*seedp)); + memcpy(heightbits,vopret.data(),vopret.size()); + return((int32_t)(vopret.size()/sizeof(uint32_t))); + } + return(-1); +} + +// komodo_heightpricebits() extracts the price data in the coinbase for nHeight +int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight) +{ + CBlockIndex *pindex; CBlock block; + if ( seedp != 0 ) + *seedp = 0; + if ( (pindex= komodo_chainactive(nHeight)) != 0 ) + { + if ( komodo_blockload(block,pindex) == 0 ) + { + return(_komodo_heightpricebits(seedp,heightbits,&block)); + } + } + fprintf(stderr,"couldnt get pricebits for %d\n",nHeight); + return(-1); +} + +/* + komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit + */ +uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance) +{ + uint64_t highprice,lowprice; + if ( refprice < 2 ) + return(0); + highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price + lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest + if ( highprice == refprice ) + highprice++; + if ( lowprice == refprice ) + lowprice--; + if ( price >= highprice ) + { + //fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); + if ( price > highprice ) // return non-zero only if we violate the tolerance + { + *maxflagp = 2; + return(highprice); + } + *maxflagp = 1; + } + else if ( price <= lowprice ) + { + //fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); + if ( price < lowprice ) + { + *maxflagp = -2; + return(lowprice); + } + *maxflagp = -1; + } + return(0); +} + +// komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance +int32_t komodo_pricecmp(int32_t nHeight, char *maxflags, uint32_t *pricebitsA, uint32_t *pricebitsB, int32_t begin, int32_t end, int64_t tolerance) +{ + int32_t i; uint32_t newprice; + for (i = begin; i < end; i++) + { + if ((newprice = komodo_pricenew(&maxflags[i], pricebitsA[i], pricebitsB[i], tolerance)) != 0) + { + fprintf(stderr, "ht.%d i.%d/%d %u vs %u -> newprice.%u out of tolerance maxflag.%d\n", nHeight, i, end, pricebitsB[i], pricebitsA[i], newprice, maxflags[i]); + return(-1); + } + } + return(0); +} + +// komodo_priceclamp() clamps any price that is beyond tolerance +int32_t komodo_priceclamp(uint32_t *pricebits, uint32_t *refprices, int32_t begin, int32_t end, int64_t tolerance) +{ + int32_t i; + uint32_t newprice; + char maxflags[KOMODO_MAXPRICES]; + + memset(maxflags, 0, sizeof(maxflags)); + for (i = begin; i < end; i++) + { + if ((newprice = komodo_pricenew(&maxflags[i], pricebits[i], refprices[i], tolerance)) != 0) + { + fprintf(stderr, "priceclamped[%d of %d] %u vs %u -> %u\n", i, end, refprices[i], pricebits[i], newprice); + pricebits[i] = newprice; + } + } + return(0); +} + +// komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight +CScript komodo_mineropret(int32_t nHeight) +{ + CScript opret; + char maxflags[KOMODO_MAXPRICES]; + uint32_t pricebits[KOMODO_MAXPRICES], prevbits[KOMODO_MAXPRICES]; + int32_t maxflag, i, n, numzero = 0; + + if (Mineropret.size() >= PRICES_SIZEBIT0) + { + n = (int32_t)(Mineropret.size() / sizeof(uint32_t)); + numzero = 1; + while (numzero > 0) + { + memcpy(pricebits, Mineropret.data(), Mineropret.size()); + for (i = numzero = 0; i < n; i++) + { + if (pricebits[i] == 0) + { + fprintf(stderr, "zero pricebits i.%d ", i); + numzero++; + } + } + if (numzero != 0) + { + fprintf(stderr, " komodo_mineropret numzero.%d vs n.%d, zeros in pricebuf, waiting 61 sec for initial prices values loading...\n", numzero, n); + komodo_cbopretupdate(1); + + if (ShutdownRequested()) + return CScript(); + sleep(61); + } + } + + std::vector processors; + PricesFeedGetCustomProcessors(processors); + + if (komodo_heightpricebits(0, prevbits, nHeight - 1) > 0) // get previous prices + { + // set working prices buffer: + memcpy(pricebits, Mineropret.data(), Mineropret.size()); + memset(maxflags, 0, sizeof(maxflags)); + + for (auto const &p : processors) + { + if (p.clamper == NULL) + { + // default clamper + if (komodo_pricecmp(nHeight, maxflags, pricebits, prevbits, p.b, p.e, PRICES_ERRORRATE) < 0) + { + // if the new prices are outside tolerance, update Mineropret with clamped prices + komodo_priceclamp(pricebits, prevbits, p.b, p.e, PRICES_ERRORRATE); + //fprintf(stderr,"update Mineropret to clamped prices\n"); + + } + } + else + p.clamper(nHeight, pricebits, prevbits, p.b, p.e, PRICES_ERRORRATE); + } + + // copy working buffer back: + memcpy(Mineropret.data(), pricebits, Mineropret.size()); + } + + int32_t i; + for (i = 0; i < Mineropret.size(); i++) + fprintf(stderr, "%02x", Mineropret[i]); + fprintf(stderr, " <- Mineropret\n"); + return(opret << OP_RETURN << Mineropret); + } + return(opret); +} + + +void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits) +{ + fprintf(stderr,"ExtremePrice dir.%d ht.%d ind.%d cmpbits.%u\n",dir,height,ind,pricebits); + ExtremePrice.dir = dir; + ExtremePrice.height = height; + ExtremePrice.blockhash = blockhash; + ExtremePrice.ind = ind; + ExtremePrice.timestamp = timestamp; + ExtremePrice.pricebits = pricebits; +} + + +/* +validate prices DTO coinbase opreturn with price data + +komodo_opretvalidate() is the entire price validation! +it prints out some useful info for debugging, like the lag from current time and prev block and the prices encoded in the opreturn. + +The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data. + +*/ +int32_t komodo_opretvalidate(const CBlock *block, CBlockIndex * const previndex, int32_t nHeight, CScript scriptPubKey) +{ + int32_t testchain_exemption = 0; + std::vector vopret; + char maxflags[KOMODO_MAXPRICES]; + uint256 bhash; double btcusd, btcgbp, btceur; + uint32_t localbits[KOMODO_MAXPRICES], pricebits[KOMODO_MAXPRICES], prevbits[KOMODO_MAXPRICES], newprice; + int32_t prevtime, lag, lag2, lag3, n, errflag, iter; + uint32_t now; + const int PRICES_EARLY_CHAIN_HEIGHT = 1000; + + + if (ASSETCHAINS_CBOPRET != 0 && nHeight > 0) + { + now = (uint32_t)time(NULL); + bhash = block->GetHash(); + GetOpReturnData(scriptPubKey, vopret); + if (vopret.size() >= PRICES_SIZEBIT0) + { + // default prices validation: + n = (int32_t)(vopret.size() / sizeof(uint32_t)); + memcpy(pricebits, vopret.data(), Mineropret.size()); + + if (nHeight > 2) + { + if (komodo_heightpricebits(0, prevbits, nHeight - 1) <= 0) + { + std::cerr << __func__ << " error: could not get prevbits for height " << nHeight-1 << std::endl; + return -1; + } + + std::vector processors; + PricesFeedGetCustomProcessors(processors); + + std::vector< std::pair > ranges; + for (const auto &p : processors) + { + if (p.validator) + { + // call the custom validator + if (p.validator(nHeight, ASSETCHAINS_BLOCKTIME, block->nTime, previndex->nTime, pricebits, prevbits, p.b, p.e) < 0) + std::cerr << __func__ << " error: custom validation function invalidated prices data for prices indexes from " << p.b << " to " << p.e << std::endl; + } + else + { + // create ranges for the default validation: + ranges.push_back(std::make_pair(p.b, p.e)); + } + } + + // proceed with the default validation: + memset(maxflags, 0, sizeof(maxflags)); + prevtime = previndex->nTime; + lag = (int32_t)(now - pricebits[0]); + lag2 = (int32_t)(pricebits[0] - prevtime); + lag3 = (int32_t)(block->nTime - pricebits[0]); + + if (lag < -60) // avoid data from future + { + fprintf(stderr, "A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n", nHeight, now, prevtime, block->nTime, pricebits[0], lag, lag2, lag3); + return(-1); + } + // we should allow lag2 check to pass for early chains + // currently minimum prices update interval = 120 sec (really 120..130) + // suppose blocktime = 180 sec + // block[i], t = T0 + // block[i+1], t = T0+180 + // earliest update t <= T0+180-130 <= T0+50 + // so lag2 could be not less than +50 on mature chain with blocktime = 180 + // but on the initial chain stage blocks could be generated faster, in several secs (> 10 sec) + // block[i], t = T0 + // block[i+1], t = T0+10 + // earliest Tupdate <= T0+10-130 <= T0-120 + // as lag2 could be even -120 for blocks per 10 sec let's allow lag2 to be not less than -130 for early chains + if (lag2 < -60 && nHeight >= PRICES_EARLY_CHAIN_HEIGHT || lag2 < -130) //testchain_exemption ) // must be close to last block timestamp + { + fprintf(stderr, "B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n", nHeight, now, prevtime, block->nTime, pricebits[0], lag, lag2, lag3, ASSETCHAINS_BLOCKTIME, lag2 < -ASSETCHAINS_BLOCKTIME); + if (nHeight > testchain_exemption) + return(-1); + } + + // explanation for lag3: + // lag3 < -60 check violation could be possible if a validation node has clock sync problems + // lag3 > ASSETCHAINS_BLOCKTIME could be possible if update interval is more than blocktime: + // block[i] t = T0 + // block[i+1] t = T0+180 + // earliest update t = T0+180-130 = T0+50 + // lag3 = 130, this is less than min blocktime = 180 + // (on early chains this also will work as we check ASSETCHAINS_BLOCKTIME param value and not real early block generation time) + if (lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME) + { + fprintf(stderr, "C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n", nHeight, now, prevtime, block->nTime, pricebits[0], lag, lag2, lag3); + if (nHeight > testchain_exemption) + return(-1); + } + + // basic price values (always present in config): + btcusd = (double)pricebits[1] / 10000; + btcgbp = (double)pricebits[2] / 10000; + btceur = (double)pricebits[3] / 10000; + fprintf(stderr, "ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n", nHeight, lag, btcusd, btcgbp, btceur, btcusd / btcgbp, btcusd / btceur, btcgbp / btceur, lag2); + + if (nHeight < testchain_exemption) + { + // set for a test chain + for (auto const &r : ranges) { + for (int32_t i = r.first; i < r.second; i++) + if (pricebits[i] == 0) + pricebits[i] = prevbits[i]; + } + pricebits[0] = prevbits[0]; // store timestamp + } + + for (const auto &r : ranges) + { + if (komodo_pricecmp(nHeight, maxflags, pricebits, prevbits, r.first, r.second, PRICES_ERRORRATE) < 0) + { + for (int32_t i = r.first; i < r.second; i++) + fprintf(stderr, "%.4f ", (double)prevbits[i] / 10000); + fprintf(stderr, " oldprices.%d\n", nHeight); + for (int32_t i = r.first; i < r.second; i++) + fprintf(stderr, "%.4f ", (double)pricebits[i] / 10000); + fprintf(stderr, " newprices.%d\n", nHeight); + + fprintf(stderr, "vs prev cmp error\n"); + return(-1); + } // else this is the good case we hope to happen + } + + if (lag < ASSETCHAINS_BLOCKTIME && Mineropret.size() >= PRICES_SIZEBIT0) + { + memcpy(localbits, Mineropret.data(), Mineropret.size()); + if (nHeight < testchain_exemption) + { + // set for a test chain + for (auto const &r : ranges) { + for (int32_t i = r.first; i < r.second; i++) + if (localbits[i] == 0) + localbits[i] = prevbits[i]; + } + localbits[0] = prevbits[0]; // store timestamp + } + for (iter = 0; iter < 2; iter++) // first iter should just refresh prices if out of tolerance + { + bool checked = false; + int32_t maxflag = 0; + + for (auto const &r : ranges) + { + for (int32_t i = r.first; i < r.second; i++) + { + if ((maxflag = maxflags[i]) != 0 && localbits[i] != 0) + { + // make sure local price is moving in right direction + fprintf(stderr, "maxflag.%d i.%d localbits.%u vs pricebits.%u prevbits.%u\n", maxflag, i, localbits[i], pricebits[i], prevbits[i]); + if (maxflag > 0 && localbits[i] < prevbits[i]) + { + if (iter == 0) { + checked = true; + break; + } + // second iteration checks recent prices to see if within local volatility + int32_t icache; + for (icache = 0; icache < KOMODO_LOCALPRICE_CACHESIZE; icache++) + { + if (PriceCache[icache][i] >= prevbits[i]) + { + fprintf(stderr, "i.%d within recent localprices[%d] %u >= %u\n", i, icache, PriceCache[icache][i], prevbits[i]); + checked = true; + break; + } + } + if (icache == KOMODO_LOCALPRICE_CACHESIZE) + { + komodo_queuelocalprice(1, nHeight, block->nTime, bhash, i, prevbits[i]); + checked = true; + break; + } + } + else if (maxflag < 0 && localbits[i] > prevbits[i]) + { + if (iter == 0) { + checked = true; + break; + } + int32_t icache; + for (icache = 0; icache < KOMODO_LOCALPRICE_CACHESIZE; icache++) + { + if (PriceCache[icache][i] <= prevbits[i]) + { + fprintf(stderr, "i.%d within recent localprices[%d] %u <= prev %u\n", i, icache, PriceCache[icache][i], prevbits[i]); + checked = true; + break; + } + } + if (icache == KOMODO_LOCALPRICE_CACHESIZE) + { + komodo_queuelocalprice(-1, nHeight, block->nTime, bhash, i, prevbits[i]); + checked = true; + break; + } + } + } + } + if (checked) + break; // break from ranges + } + if (checked) + { + if (iter == 0) + { + fprintf(stderr, "force update prices\n"); + komodo_cbopretupdate(1); + memcpy(localbits, Mineropret.data(), Mineropret.size()); + } + else + { + std::cerr << __func__ << " prices opreturn not valid" << std::endl; + return(-1); + } + } + } + } + } + if (bhash == ExtremePrice.blockhash) + { + fprintf(stderr, "approved a previously extreme price based on new data ht.%d vs %u vs %u\n", ExtremePrice.height, ExtremePrice.timestamp, (uint32_t)block->nTime); + memset(&ExtremePrice, 0, sizeof(ExtremePrice)); + } + return(0); + } + else + fprintf(stderr, "wrong (too big) prices opreturn size %d vs %d, scriptPubKey size %d [%02x]\n", (int32_t)vopret.size(), (int32_t)Mineropret.size(), (int32_t)scriptPubKey.size(), (scriptPubKey.size() > 0 ? scriptPubKey[0] : '\0')); + return(-1); + } + return(0); +} + +char *nonportable_path(char *str) +{ + int32_t i; + for (i=0; str[i]!=0; i++) + if ( str[i] == '/' ) + str[i] = '\\'; + return(str); +} + +char *portable_path(char *str) +{ +#ifdef _WIN32 + return(nonportable_path(str)); +#else +#ifdef __PNACL + /*int32_t i,n; + if ( str[0] == '/' ) + return(str); + else + { + n = (int32_t)strlen(str); + for (i=n; i>0; i--) + str[i] = str[i-1]; + str[0] = '/'; + str[n+1] = 0; + }*/ +#endif + return(str); +#endif +} + +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) +{ + FILE *fp; + long filesize,buflen = *allocsizep; + uint8_t *buf = *bufp; + *lenp = 0; + if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) + { + fseek(fp,0,SEEK_END); + filesize = ftell(fp); + if ( filesize == 0 ) + { + fclose(fp); + *lenp = 0; + //printf("loadfile null size.(%s)\n",fname); + return(0); + } + if ( filesize > buflen ) + { + *allocsizep = filesize; + *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); + } + rewind(fp); + if ( buf == 0 ) + printf("Null buf ???\n"); + else + { + if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) + printf("error reading filesize.%ld\n",(long)filesize); + buf[filesize] = 0; + } + fclose(fp); + *lenp = filesize; + //printf("loaded.(%s)\n",buf); + } //else printf("OS_loadfile couldnt load.(%s)\n",fname); + return(buf); +} + +void *filestr(long *allocsizep,char *_fname) +{ + long filesize = 0; char *fname,*buf = 0; void *retptr; + *allocsizep = 0; + fname = (char *)malloc(strlen(_fname)+1); + strcpy(fname,_fname); + retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); + free(fname); + return(retptr); +} + +cJSON *send_curl(char *url,char *fname) +{ + long fsize; char curlstr[1024],*jsonstr; cJSON *json=0; + sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname); + if ( system(curlstr) == 0 ) + { + if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 ) + { + json = cJSON_Parse(jsonstr); + free(jsonstr); + } + } + return(json); +} + +// get_urljson just returns the JSON returned by the URL using issue_curl + + +/* +const char *Techstocks[] = +{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN" +}; +const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; +const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; +*/ + +cJSON *get_urljson(char *url) +{ + char *jsonstr; + cJSON *json = 0; + if ( (jsonstr= issue_curl(url)) != 0 ) + { + //fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr); + json = cJSON_Parse(jsonstr); + //free(jsonstr); + cJSON_free(jsonstr); + } + return(json); +} + + +// komodo_cbopretupdate() obtains the external price data and encodes it into Mineropret, which will then be used by the miner and validation +// save history, use new data to approve past rejection, where is the auto-reconsiderblock? +int32_t komodo_cbopretsize(uint64_t flags) +{ + int32_t size = 0; + if ( (ASSETCHAINS_CBOPRET & 1) != 0 ) + { + size = PricesFeedSymbolsCount() * sizeof(uint32_t); + } + return(size); +} + +extern uint256 Queued_reconsiderblock; + +void komodo_cbopretupdate(int32_t forceflag) +{ + static uint32_t /*lasttime,lastbtc,*/pending; + static uint32_t pricebits[4], pricebuf[KOMODO_MAXPRICES]; //, forexprices[sizeof(Forex) / sizeof(*Forex)]; + uint32_t flags=0; + CBlockIndex *pindex; + uint32_t now; + + if (ShutdownRequested()) + return; + + if ( Queued_reconsiderblock != zeroid ) + { + fprintf(stderr,"Queued_reconsiderblock %s\n",Queued_reconsiderblock.GetHex().c_str()); + komodo_reconsiderblock(Queued_reconsiderblock); + Queued_reconsiderblock = zeroid; + } + if ( forceflag != 0 && pending != 0 ) + { + while ( pending != 0 ) + fprintf(stderr,"pricewait "), sleep(1); // reentrant call is waiting until mineropret is updated + return; + } + pending = 1; // prevent reentry to the function + //now = (uint32_t)time(NULL); + if ( (ASSETCHAINS_CBOPRET & 1) != 0 ) + { + //time_t timestamp; + uint32_t count = PricesFeedPoll(pricebuf, sizeof(pricebuf) / sizeof(pricebuf[0]), &now); + + if (count == PF_BUFOVERFLOW) { + std::cerr << "price buffer overflow, shutdown..." << std::endl; + StartShutdown(); + } + + if (count > 0) { + komodo_PriceCache_shift(); + memcpy(PriceCache[0], pricebuf, count * sizeof(uint32_t)); + flags = 1; //old code compatibility + } + + if ( flags != 0 ) + { + uint32_t opretsize = komodo_cbopretsize(ASSETCHAINS_CBOPRET); + if (Mineropret.size() < opretsize) + Mineropret.resize(opretsize); + +// if ( (flags & 1) != 0 ) +// lastbtc = now; +// if ( (flags & 2) != 0 ) +// lasttime = now; + memcpy(Mineropret.data(), PriceCache[0], opretsize); + + // invalidate block with extreme prices: + if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < count && now < ExtremePrice.timestamp+3600 ) + { + fprintf(stderr,"cmp dir.%d PriceCache[0][ExtremePrice.ind] %u >= %u ExtremePrice.pricebits\n",ExtremePrice.dir,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); + if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) + { + fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); + if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) + pindex->nStatus &= ~BLOCK_FAILED_MASK; + else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str()); + } + } + // high volatility still strands nodes so we need to check new prices to approve a stuck block + // scan list of stuck blocks (one?) and auto reconsiderblock if it changed state + + //int32_t i; for (i=0; i= 1) + return COIN / conversionmult; + else + return COIN; // this should not happen + } + return(0); +} + +char *komodo_pricename(char *name,int32_t ind) +{ + strcpy(name,"error"); + if ( (ASSETCHAINS_CBOPRET & 1) != 0 && ind < KOMODO_MAXPRICES ) + { + if (ind == 0) { + strcpy(name, "timestamp"); + return name; + } + return PricesFeedSymbolName(name, ind); + } + return(0); +} +// finds index for its symbol name +int32_t komodo_priceind(const char *symbol) +{ + char name[PRICES_MAXNAMELENGTH + 1]; + int32_t n = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t)); + + for (int i=1; i= KOMODO_MAXPRICES ) + return(-1); + mult = komodo_pricemult_to10e8(ind); + if ( nonzprices != 0 ) + memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW); + //for (i=0; i= PRICES_DAYWINDOW ) + i = 0; + if ( (price= rawprices[i*rawskip]) == 0 ) + { + fprintf(stderr,"null rawprice.[%d]\n",i); + return(-1); + } + if ( price >= lowprice && price <= highprice ) + { + //fprintf(stderr,"%.1f ",(double)price/10000); + sum += price; + correlation++; + if ( correlation > (PRICES_DAYWINDOW>>1) ) + { + if ( nonzprices == 0 ) + return(refprice * mult); + //fprintf(stderr,"-> %.4f\n",(double)sum*mult/correlation); + //return(sum*mult/correlation); + n = 0; + i = (iter + seed) % PRICES_DAYWINDOW; + for (k=0; k= PRICES_DAYWINDOW ) + i = 0; + if ( n > (PRICES_DAYWINDOW>>1) ) + nonzprices[i] = 0; + else + { + price = rawprices[i*rawskip]; + if ( price < lowprice || price > highprice ) + nonzprices[i] = 0; + else + { + nonzprices[i] = price; + //fprintf(stderr,"(%d %u) ",i,rawprices[i*rawskip]); + n++; + } + } + } + //fprintf(stderr,"ind.%d iter.%d j.%d i.%d n.%d correlation.%d ref %llu -> %llu\n",ind,iter,j,i,n,correlation,(long long)refprice,(long long)sum/correlation); + if ( n != correlation ) + return(-1); + sum = den = n = 0; + for (i=0; i %.8f\n",(long long)firstprice,((double)(sum*mult) / den) / COIN); + return((sum * mult) / den); + } + } + } + if ( correlation > maxcorrelation ) + maxcorrelation = correlation; + } + //fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice); + return(0); +} + +int64_t _pairave64(int64_t valA,int64_t valB) +{ + if ( valA != 0 && valB != 0 ) + return((valA + valB) / 2); + else if ( valA != 0 ) return(valA); + else return(valB); +} + +int64_t _pairdiff64(register int64_t valA,register int64_t valB) +{ + if ( valA != 0 && valB != 0 ) + return(valA - valB); + else return(0); +} + +int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width) +{ + register int32_t nonz,j; register int64_t sum,price; + nonz = 0; + sum = 0; + for (j=-width; j<=width; j++) + { + price = buf[i + j]; + if ( price != 0 ) + { + sum += price; + nonz++; + } + } + if ( nonz != 0 ) + sum /= nonz; + return(sum); +} + +void buf_trioave64(int64_t dest[],int64_t src[],int32_t n) +{ + register int32_t i,j,width = 3; + for (i=0; i<128; i++) + src[i] = 0; + //for (i=n-width-1; i>width; i--) + // dest[i] = balanced_ave(src,i,width); + //for (i=width; i>0; i--) + // dest[i] = balanced_ave(src,i,i); + for (i=1; i *(int64_t *)b) return 1; + else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism + return(-1); + else return(1); +} + +static void sort64(int64_t *l, int32_t llen) +{ + qsort(l,llen,sizeof(uint64_t),cmp_llu); +} + +static int revcmp_llu(const void *a, const void*b) +{ + if(*(int64_t *)a < *(int64_t *)b) return 1; + else if(*(int64_t *)a > *(int64_t *)b) return -1; + else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism + return(-1); + else return(1); +} + +static void revsort64(int64_t *l, int32_t llen) +{ + qsort(l,llen,sizeof(uint64_t),revcmp_llu); +} + +int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) +{ + int32_t i,dir=0; int64_t sum=0,nonzprice,price,halfave,thirdave,fourthave,decayprice; + if ( PRICES_DAYWINDOW < 2 ) + return(0); + for (i=0; i price ) // rising prices + sort64(buf,PRICES_DAYWINDOW); + else revsort64(buf,PRICES_DAYWINDOW); + decayprice = buf[0]; + for (i=0; i %.8f\n",halfave 0 && PRICES[0].fp != 0 && createflag != 0 ) + { + fseek(PRICES[0].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET); + fputc(0,PRICES[0].fp); + fflush(PRICES[0].fp); + } + fprintf(stderr,"pricesinit done i.%d num.%d numprices.%d\n",i,num,(int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t))); + if ( i != num || i != komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t) ) + { + fprintf(stderr,"fatal error opening prices files, start shutdown\n"); + StartShutdown(); + } + return(0); +} + +pthread_mutex_t pricemutex; + +// PRICES file layouts +// [0] rawprice32 / timestamp +// [1] correlated +// [2] 24hr ave +// [3] to [7] reserved + +void komodo_pricesupdate(int32_t height,CBlock *pblock) +{ + static int numprices; static uint32_t *ptr32; static int64_t *ptr64,*tmpbuf; + int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[PRICES_MAXDATAPOINTS*2]; + width = PRICES_DAYWINDOW;//(2*PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH); + if ( numprices == 0 ) + { + pthread_mutex_init(&pricemutex,0); + numprices = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t)); + ptr32 = (uint32_t *)calloc(sizeof(uint32_t),numprices * width); + ptr64 = (int64_t *)calloc(sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS); + tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW); + fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64); + } + if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) + { + //for (ind=0; ind PRICES_DAYWINDOW ) + { + fseek(PRICES[0].fp,(height-width+1) * numprices * sizeof(uint32_t),SEEK_SET); + if ( fread(ptr32,sizeof(uint32_t),width*numprices,PRICES[0].fp) == width*numprices ) + { + rngval = seed; + for (ind=1; ind 0 ) + { + fseek(PRICES[ind].fp,height * sizeof(int64_t) * PRICES_MAXDATAPOINTS,SEEK_SET); + memset(buf,0,sizeof(buf)); + buf[0] = rawprices[ind]; + buf[1] = rawprices[0]; // timestamp + memcpy(&buf[2],&correlated,sizeof(correlated)); + if ( fwrite(buf,1,sizeof(buf),PRICES[ind].fp) != sizeof(buf) ) + fprintf(stderr,"error fwrite buf for ht.%d ind.%d\n",height,ind); + else if ( height > PRICES_DAYWINDOW*2 ) + { + fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); + if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS,PRICES[ind].fp) == PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS ) + { + if ( (smoothed= komodo_priceave(tmpbuf,&ptr64[(PRICES_DAYWINDOW-1)*PRICES_MAXDATAPOINTS+1],-PRICES_MAXDATAPOINTS)) > 0 ) + { + fseek(PRICES[ind].fp,(height * PRICES_MAXDATAPOINTS + 2) * sizeof(int64_t),SEEK_SET); + if ( fwrite(&smoothed,1,sizeof(smoothed),PRICES[ind].fp) != sizeof(smoothed) ) + fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind); + else fflush(PRICES[ind].fp); + } else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind); + } else fprintf(stderr,"error fread ptr64 for ht.%d ind.%d\n",height,ind); + } + } //else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind); + } + //fprintf(stderr,"height.%d\n",height); + } else fprintf(stderr,"error reading rawprices for ht.%d\n",height); + } // else fprintf(stderr,"height.%d <= width.%d\n",height,width); + pthread_mutex_unlock(&pricemutex); + } else fprintf(stderr,"null PRICES[0].fp\n"); + } else fprintf(stderr,"numprices mismatch, height.%d\n",height); +} + +int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks) +{ + FILE *fp; int32_t retval = PRICES_MAXDATAPOINTS; + pthread_mutex_lock(&pricemutex); + if ( ind < KOMODO_MAXPRICES && (fp= PRICES[ind].fp) != 0 ) + { + fseek(fp,height * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); + if ( fread(buf64,sizeof(int64_t),numblocks*PRICES_MAXDATAPOINTS,fp) != numblocks*PRICES_MAXDATAPOINTS ) + retval = -1; + } + pthread_mutex_unlock(&pricemutex); + return(retval); +} + +// place to add miner's created transactions +UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey &mypk); + +void komodo_createminerstransactions() +{ + std::vector minersTransactions; + CBlockIndex *pIndexTip = chainActive.LastTip(); + int32_t nHeight = pIndexTip ? pIndexTip->GetHeight() : 0; + + // call here creation of 'miners' transactions... + + // send miner created transaction + CPubKey minerpk = pubkey2pk(Mypubkey()); + for (const auto &tx : minersTransactions) + { + std::string hextx = HexStr(E_MARSHAL(ss << tx)); + UniValue rpcparams(UniValue::VARR), txparam(UniValue::VOBJ); + txparam.setStr(hextx); + rpcparams.push_back(txparam); + try { + // TODO: change sendrawtransaction to low-level RelayTransaction function + sendrawtransaction(rpcparams, false, CPubKey()); // NOTE: throws error, so catch them! + } + catch (std::runtime_error error) + { + LOGSTREAMFN("miner", CCLOG_ERROR, stream << std::string("could not send miner created transaction: bad parameters: ") + error.what()); + } + catch (UniValue error) + { + LOGSTREAMFN("miner", CCLOG_ERROR, stream << std::string("error: could not send miner created tx: ") + error.getValStr()); + } + } + +} diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 450ffa6b5c6..3fa2cf209e1 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1,3 +1,4 @@ + /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -12,1250 +13,65 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once // paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse #include "komodo_defs.h" +#include "cc/CCPrices.h" +#include "cc/pricesfeed.h" + +#define KOMODO_MAXPRICES 2048 -/*#include "secp256k1/include/secp256k1.h" -#include "secp256k1/include/secp256k1_schnorrsig.h" -#include "secp256k1/include/secp256k1_musig.h" - -int32_t dummy_linker_tricker() -{ - secp256k1_context *ctx = 0; std::vector musig64; CPubKey pk; secp256k1_schnorrsig musig; secp256k1_pubkey combined_pk; - if ( secp256k1_schnorrsig_parse((const secp256k1_context *)ctx,&musig,(const uint8_t *)&musig64[0]) > 0 && secp256k1_ec_pubkey_parse(ctx,&combined_pk,pk.begin(),33) > 0 ) - return(1); -}*/ - -int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx); - -int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) -{ - int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed,maxval; - *available = *deposited = *issued = *withdrawn = *approved = *redeemed = 0; - if ( (baseid= komodo_baseid(base)) >= 0 ) - { - if ( (sp= komodo_stateptrget(base)) != 0 ) - { - *deposited = sp->deposited; - *issued = sp->issued; - *withdrawn = sp->withdrawn; - *approved = sp->approved; - *redeemed = sp->redeemed; - maxval = sp->approved; - if ( sp->withdrawn > maxval ) - maxval = sp->withdrawn; - netliability = (sp->issued - maxval) - sp->shorted; - maxallowed = komodo_maxallowed(baseid); - if ( netliability < maxallowed ) - *available = (maxallowed - netliability); - //printf("%llu - %llu %s %.8f %.8f %.8f %.8f %.8f\n",(long long)maxallowed,(long long)netliability,base,dstr(*deposited),dstr(*issued),dstr(*withdrawn),dstr(*approved),dstr(*redeemed)); - return(0); - } else printf("pax_fiatstatus cant get basesp.%s\n",base); - } // else printf("pax_fiatstatus illegal base.%s\n",base); - return(-1); -} - -void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type) -{ - memcpy(buf,&txid,32); - memcpy(&buf[32],&vout,2); - buf[34] = type; -} - -struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type) -{ - struct pax_transaction *pax; uint8_t buf[35]; - std::lock_guard lock(komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - return(pax); -} - -struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout) -{ - struct pax_transaction *pax; int32_t i; uint8_t types[] = { 'I', 'D', 'X', 'A', 'W' }; - for (i=0; i lock(komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - if ( pax == 0 ) - { - pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); - pax->txid = txid; - pax->vout = vout; - pax->type = type; - memcpy(pax->buf,buf,sizeof(pax->buf)); - HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); - //printf("ht.%d create pax.%p mark.%d\n",height,pax,mark); - } - if ( pax != 0 ) - { - pax->marked = mark; - //if ( height > 214700 || pax->height > 214700 ) - // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - - } - return(pax); -} - -void komodo_paxdelete(struct pax_transaction *pax) -{ - return; // breaks when out of order - std::lock_guard lock(komodo_mutex); - HASH_DELETE(hh,PAX,pax); -} - -void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context -{ - struct pax_transaction *pax; uint8_t buf[35]; int32_t addflag = 0; struct komodo_state *sp; char str[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*s; - //if ( KOMODO_PAX == 0 ) - // return; - //if ( strcmp(symbol,ASSETCHAINS_SYMBOL) != 0 ) - // return; - sp = komodo_stateptr(str,dest); - { - std::lock_guard lock(komodo_mutex); - pax_keyset(buf,txid,vout,type); - HASH_FIND(hh,PAX,buf,sizeof(buf),pax); - if ( pax == 0 ) - { - pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); - pax->txid = txid; - pax->vout = vout; - pax->type = type; - memcpy(pax->buf,buf,sizeof(pax->buf)); - HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax); - addflag = 1; - if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - { - int32_t i; for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&txid)[i]); - printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source); - } - } - } - if ( coinaddr != 0 ) - { - strcpy(pax->coinaddr,coinaddr); - if ( value != 0 ) - pax->komodoshis = value; - if ( symbol != 0 ) - strcpy(pax->symbol,symbol); - if ( source != 0 ) - strcpy(pax->source,source); - if ( fiatoshis != 0 ) - pax->fiatoshis = fiatoshis; - if ( rmd160 != 0 ) - memcpy(pax->rmd160,rmd160,20); - if ( height != 0 ) - pax->height = height; - if ( otherheight != 0 ) - pax->otherheight = otherheight; - } - else - { - pax->marked = height; - //printf("pax.%p MARK DEPOSIT ht.%d other.%d\n",pax,height,otherheight); - } -} - -int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax) -{ - int32_t i,len = 0; - if ( rwflag == 1 ) - { - for (i=0; i<32; i++) - opretbuf[len++] = ((uint8_t *)&pax->txid)[i]; - opretbuf[len++] = pax->vout & 0xff; - opretbuf[len++] = (pax->vout >> 8) & 0xff; - } - else - { - for (i=0; i<32; i++) - ((uint8_t *)&pax->txid)[i] = opretbuf[len++]; - //for (i=0; i<32; i++) - // printf("%02x",((uint8_t *)&pax->txid)[31-i]); - pax->vout = opretbuf[len++]; - pax->vout += ((uint32_t)opretbuf[len++] << 8); - //printf(" txid v.%d\n",pax->vout); - } - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height); - len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight); - if ( rwflag != 0 ) - { - memcpy(&opretbuf[len],pax->rmd160,20), len += 20; - for (i=0; i<4; i++) - opretbuf[len++] = pax->source[i]; - } - else - { - memcpy(pax->rmd160,&opretbuf[len],20), len += 20; - for (i=0; i<4; i++) - pax->source[i] = opretbuf[len++]; - } - return(len); -} - -int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo) -{ - struct pax_transaction p,*pax; int32_t i,n=0,j,len=0,incr,height,otherheight; uint8_t type,rmd160[20]; uint64_t fiatoshis; char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - //if ( KOMODO_PAX == 0 ) - // return(0); - incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); - //41e77b91cb68dc2aa02fa88550eae6b6d44db676a7e935337b6d1392d9718f03cb0200305c90660400000000fbcbeb1f000000bde801006201000058e7945ad08ddba1eac9c9b6c8e1e97e8016a2d152 - - // 41e94d736ec69d88c08b5d238abeeca609c02357a8317e0d56c328bcb1c259be5d0200485bc80200000000404b4c000000000059470200b80b000061f22ba7d19fe29ac3baebd839af8b7127d1f9075553440046bb4cc7a3b5cd39dffe7206507a3482a00780e617f68b273cce9817ed69298d02001069ca1b0000000080f0fa02000000005b470200b90b000061f22ba7d19fe29ac3baebd839af8b7127d1f90755 - - //for (i=0; i>>>>>> %s: (%s) fiat %.8f kmdheight.%d other.%d -> %s %.8f\n",type=='A'?"approvedA":"issuedX",baseids[n]>=0?CURRENCIES[baseids[n]]:"???",dstr(p.fiatoshis),kmdheights[n],otherheights[n],coinaddr,dstr(values[n])); - } - } - } - else - { - for (i=0; i<4; i++) - base[i] = opretbuf[opretlen-4+i]; - for (j=0; j<32; j++) - { - ((uint8_t *)&txids[n])[j] = opretbuf[len++]; - //printf("%02x",((uint8_t *)&txids[n])[j]); - } - vouts[n] = opretbuf[len++]; - vouts[n] = (opretbuf[len++] << 8) | vouts[n]; - baseids[n] = komodo_baseid(base); - if ( (pax= komodo_paxfinds(txids[n],vouts[n])) != 0 ) - { - values[n] = (strcmp("KMD",base) == 0) ? pax->komodoshis : pax->fiatoshis; - srcvalues[n] = (strcmp("KMD",base) == 0) ? pax->fiatoshis : pax->komodoshis; - kmdheights[n] = pax->height; - otherheights[n] = pax->otherheight; - memcpy(&rmd160s[n * 20],pax->rmd160,20); - } - } - //printf(" komodo_issued_opreturn issuedtxid v%d i.%d opretlen.%d\n",vouts[n],n,opretlen); - } - } - return(n); -} - -int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed) -{ - int32_t ratio; - if ( seed == 0 && checkvalue != 0 ) - { - ratio = ((value << 6) / checkvalue); - if ( ratio >= 60 && ratio <= 67 ) - return(0); - else - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio); - return(-1); - } - } - else if ( checkvalue != 0 ) - { - ratio = ((value << 10) / checkvalue); - if ( ratio >= 1023 && ratio <= 1025 ) - return(0); - } - return(value != checkvalue); -} - -uint64_t komodo_paxtotal() -{ - struct pax_transaction *pax,*pax2,*tmp,*tmp2; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN],*str; int32_t i,ht; int64_t checktoshis; uint64_t seed,total = 0; struct komodo_state *basesp; - if ( KOMODO_PASSPORT_INITDONE == 0 ) //KOMODO_PAX == 0 || - return(0); - if ( komodo_isrealtime(&ht) == 0 ) - return(0); - else - { - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->marked != 0 ) - continue; - if ( pax->type == 'A' || pax->type == 'D' || pax->type == 'X' ) - str = pax->symbol; - else str = pax->source; - basesp = komodo_stateptrget(str); - if ( basesp != 0 && pax->didstats == 0 ) - { - if ( pax->type == 'I' && (pax2= komodo_paxfind(pax->txid,pax->vout,'D')) != 0 ) - { - if ( pax2->fiatoshis != 0 ) - { - pax->komodoshis = pax2->komodoshis; - pax->fiatoshis = pax2->fiatoshis; - basesp->issued += pax->fiatoshis; - pax->didstats = 1; - if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p issued %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,str,dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight); - pax2->marked = pax->height; - pax->marked = pax->height; - } - } - else if ( pax->type == 'W' ) - { - //bitcoin_address(coinaddr,addrtype,rmd160,20); - if ( (checktoshis= komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis)) != 0 ) - { - if ( komodo_paxcmp(pax->source,pax->height,pax->komodoshis,checktoshis,seed) != 0 ) - { - pax->marked = pax->height; - //printf("WITHDRAW.%s mark <- %d %.8f != %.8f\n",pax->source,pax->height,dstr(checktoshis),dstr(pax->komodoshis)); - } - else if ( pax->validated == 0 ) - { - pax->validated = pax->komodoshis = checktoshis; - //int32_t j; for (j=0; j<32; j++) - // printf("%02x",((uint8_t *)&pax->txid)[j]); - //if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 ) - // printf(" v%d %p got WITHDRAW.%s kmd.%d ht.%d %.8f -> %.8f/%.8f\n",pax->vout,pax,pax->source,pax->height,pax->otherheight,dstr(pax->fiatoshis),dstr(pax->komodoshis),dstr(checktoshis)); - } - } - } - } - } - } - komodo_stateptr(symbol,dest); - HASH_ITER(hh,PAX,pax,tmp) - { - pax->ready = 0; - if ( 0 && pax->type == 'A' ) - printf("%p pax.%s <- %s marked.%d %.8f -> %.8f validated.%d approved.%d\n",pax,pax->symbol,pax->source,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0); - if ( pax->marked != 0 ) - continue; - if ( strcmp(symbol,pax->symbol) == 0 || pax->type == 'A' ) - { - if ( pax->marked == 0 ) - { - if ( komodo_is_issuer() != 0 ) - { - if ( pax->validated != 0 && pax->type == 'D' ) - { - total += pax->fiatoshis; - pax->ready = 1; - } - } - else if ( pax->approved != 0 && pax->type == 'A' ) - { - if ( pax->validated != 0 ) - { - total += pax->komodoshis; - pax->ready = 1; - } - else - { - seed = 0; - checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis); - //printf("paxtotal PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN); - //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight); - if ( seed != 0 && checktoshis != 0 ) - { - if ( checktoshis == pax->komodoshis ) - { - total += pax->komodoshis; - pax->validated = pax->komodoshis; - pax->ready = 1; - } else pax->marked = pax->height; - } - } - } - if ( 0 && pax->ready != 0 ) - printf("%p (%c) pax.%s marked.%d %.8f -> %.8f validated.%d approved.%d ready.%d ht.%d\n",pax,pax->type,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->validated != 0,pax->approved != 0,pax->ready,pax->height); - } - } - } - //printf("paxtotal %.8f\n",dstr(total)); - return(total); -} - -static int _paxorder(const void *a,const void *b) -{ -#define pax_a (*(struct pax_transaction **)a) -#define pax_b (*(struct pax_transaction **)b) - uint64_t aval,bval; - aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height; - bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height; - if ( bval > aval ) - return(-1); - else if ( bval < aval ) - return(1); - return(0); -#undef pax_a -#undef pax_b -} - -int32_t komodo_pending_withdraws(char *opretstr) // todo: enforce deterministic order -{ - struct pax_transaction *pax,*pax2,*tmp,*paxes[64]; uint8_t opretbuf[16384*4]; int32_t i,n,ht,len=0; uint64_t total = 0; - if ( KOMODO_PAX == 0 || KOMODO_PASSPORT_INITDONE == 0 ) - return(0); - if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 ) - return(0); - n = 0; - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->type == 'W' ) - { - if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'A')) != 0 ) - { - if ( pax2->approved != 0 ) - pax->approved = pax2->approved; - } - else if ( (pax2= komodo_paxfind(pax->txid,pax->vout,'X')) != 0 ) - pax->approved = pax->height; - //printf("pending_withdraw: pax %s marked.%u approved.%u validated.%llu\n",pax->symbol,pax->marked,pax->approved,(long long)pax->validated); - if ( pax->marked == 0 && pax->approved == 0 && pax->validated != 0 ) //strcmp((char *)"KMD",pax->symbol) == 0 && - { - if ( n < sizeof(paxes)/sizeof(*paxes) ) - { - paxes[n++] = pax; - //int32_t j; for (j=0; j<32; j++) - // printf("%02x",((uint8_t *)&pax->txid)[j]); - //printf(" %s.(kmdht.%d ht.%d marked.%u approved.%d validated %.8f) %.8f\n",pax->source,pax->height,pax->otherheight,pax->marked,pax->approved,dstr(pax->validated),dstr(pax->komodoshis)); - } - } - } - } - opretstr[0] = 0; - if ( n > 0 ) - { - opretbuf[len++] = 'A'; - qsort(paxes,n,sizeof(*paxes),_paxorder); - for (i=0; i>3)*7 ) - len += komodo_rwapproval(1,&opretbuf[len],paxes[i]); - } - if ( len > 0 ) - init_hexbytes_noT(opretstr,opretbuf,len); - } - //fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal())); - return(len); -} - -int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo) -{ - struct pax_transaction *pax,*tmp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint8_t *script,opcode,opret[16384*4],data[16384*4]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask,sum = 0; - if ( KOMODO_PASSPORT_INITDONE == 0 )//KOMODO_PAX == 0 || - return(0); - struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD"); - sp = komodo_stateptr(symbol,dest); - strcpy(symbol,base); - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 ) - return(0); - PENDING_KOMODO_TX = 0; - for (i=0; i<3; i++) - { - if ( komodo_isrealtime(&ht) != 0 ) - break; - sleep(1); - } - if ( i == 3 ) - { - if ( tokomodo == 0 ) - printf("%s not realtime ht.%d\n",ASSETCHAINS_SYMBOL,ht); - return(0); - } - if ( tokomodo == 0 ) - { - opcode = 'I'; - } - else - { - opcode = 'X'; - if ( 1 || komodo_paxtotal() == 0 ) - return(0); - } - HASH_ITER(hh,PAX,pax,tmp) - { - if ( pax->type != 'D' && pax->type != 'A' ) - continue; - { -#ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE - if ( pax->height > 236000 ) - { - if ( kmdsp != 0 && kmdsp->NOTARIZED_HEIGHT >= pax->height ) - pax->validated = pax->komodoshis; - else if ( kmdsp->CURRENT_HEIGHT > pax->height+30 ) - pax->validated = pax->ready = 0; - } - else - { - if ( kmdsp != 0 && (kmdsp->NOTARIZED_HEIGHT >= pax->height || kmdsp->CURRENT_HEIGHT > pax->height+30) ) // assumes same chain as notarize - pax->validated = pax->komodoshis; - else pax->validated = pax->ready = 0; - } -#else - pax->validated = pax->komodoshis; -#endif - } - if ( ASSETCHAINS_SYMBOL[0] != 0 && (pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis) ) - { - //if ( pax->height > 214700 || strcmp(ASSETCHAINS_SYMBOL,symbol) == 0 ) - // printf("miner.[%s]: skip %s %.8f when avail %.8f deposited %.8f, issued %.8f withdrawn %.8f approved %.8f redeemed %.8f\n",ASSETCHAINS_SYMBOL,symbol,dstr(pax->fiatoshis),dstr(available),dstr(deposited),dstr(issued),dstr(withdrawn),dstr(approved),dstr(redeemed)); - continue; - } - /*printf("pax.%s marked.%d %.8f -> %.8f ready.%d validated.%d\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0); - if ( pax->marked != 0 || (pax->type != 'D' && pax->type != 'A') || pax->ready == 0 ) - { - printf("reject 2\n"); - continue; - }*/ - if ( ASSETCHAINS_SYMBOL[0] != 0 && (strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 || pax->ready == 0) ) - { - if ( strcmp(pax->symbol,ASSETCHAINS_SYMBOL) == 0 ) - printf("pax->symbol.%s != %s or null pax->validated %.8f ready.%d ht.(%d %d)\n",pax->symbol,symbol,dstr(pax->validated),pax->ready,kmdsp->CURRENT_HEIGHT,pax->height); - pax->marked = pax->height; - continue; - } - if ( pax->ready == 0 ) - continue; - if ( pax->type == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( kmdsp != 0 ) - { - if ( (baseid= komodo_baseid(pax->symbol)) < 0 || ((1LL << baseid) & sp->RTmask) == 0 ) - { - printf("not RT for (%s) %llx baseid.%d %llx\n",pax->symbol,(long long)sp->RTmask,baseid,(long long)(1LL< %.8f ready.%d validated.%d approved.%d\n",tokomodo,pax->type,pax,pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis),pax->ready!=0,pax->validated!=0,pax->approved!=0); - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - if ( opcode == 'I' ) - { - sum += pax->fiatoshis; - if ( sum > available ) - break; - } - txNew->vout.resize(numvouts+1); - txNew->vout[numvouts].nValue = (opcode == 'I') ? pax->fiatoshis : pax->komodoshis; - txNew->vout[numvouts].scriptPubKey.resize(25); - script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; - *script++ = 0x76; - *script++ = 0xa9; - *script++ = 20; - memcpy(script,pax->rmd160,20), script += 20; - *script++ = 0x88; - *script++ = 0xac; - if ( tokomodo == 0 ) - { - for (i=0; i<32; i++) - data[len++] = ((uint8_t *)&pax->txid)[i]; - data[len++] = pax->vout & 0xff; - data[len++] = (pax->vout >> 8) & 0xff; - PENDING_KOMODO_TX += pax->fiatoshis; - } - else - { - len += komodo_rwapproval(1,&data[len],pax); - PENDING_KOMODO_TX += pax->komodoshis; - printf(" len.%d vout.%u DEPOSIT %.8f <- pax.%s pending ht %d %d %.8f | ",len,pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,pax->height,pax->otherheight,dstr(PENDING_KOMODO_TX)); - } - if ( numvouts++ >= 64 || sum > COIN ) - break; - } - if ( numvouts > 1 ) - { - if ( tokomodo != 0 ) - strcpy(symbol,(char *)"KMD"); - for (i=0; symbol[i]!=0; i++) - data[len++] = symbol[i]; - data[len++] = 0; - for (i=0; ivout.resize(numvouts+1); - txNew->vout[numvouts].nValue = 0; - txNew->vout[numvouts].scriptPubKey.resize(opretlen); - script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; - memcpy(script,opret,opretlen); - for (i=0; i<8; i++) - printf("%02x",opret[i]); - printf(" <- opret, MINER deposits.%d (%s) vouts.%d %.8f opretlen.%d\n",tokomodo,ASSETCHAINS_SYMBOL,numvouts,dstr(PENDING_KOMODO_TX),opretlen); - return(1); - } - return(0); -} - -const char *banned_txids[] = -{ - "78cb4e21245c26b015b888b14c4f5096e18137d2741a6de9734d62b07014dfca", // vout1 only 233559 - "00697be658e05561febdee1aafe368b821ca33fbb89b7027365e3d77b5dfede5", //234172 - "e909465788b32047c472d73e882d79a92b0d550f90be008f76e1edaee6d742ea", //234187 - "f56c6873748a327d0b92b8108f8ec8505a2843a541b1926022883678fb24f9dc", //234188 - "abf08be07d8f5b3a433ddcca7ef539e79a3571632efd6d0294ec0492442a0204", //234213 - "3b854b996cc982fba8c06e76cf507ae7eed52ab92663f4c0d7d10b3ed879c3b0", //234367 - "fa9e474c2cda3cb4127881a40eb3f682feaba3f3328307d518589024a6032cc4", //234635 - "ca746fa13e0113c4c0969937ea2c66de036d20274efad4ce114f6b699f1bc0f3", //234662 - "43ce88438de4973f21b1388ffe66e68fda592da38c6ef939be10bb1b86387041", //234697 - "0aeb748de82f209cd5ff7d3a06f65543904c4c17387c9d87c65fd44b14ad8f8c", //234899 - "bbd3a3d9b14730991e1066bd7c626ca270acac4127131afe25f877a5a886eb25", //235252 - "fa9943525f2e6c32cbc243294b08187e314d83a2870830180380c3c12a9fd33c", //235253 - "a01671c8775328a41304e31a6693bbd35e9acbab28ab117f729eaba9cb769461", //235265 - "2ef49d2d27946ad7c5d5e4ab5c089696762ff04e855f8ab48e83bdf0cc68726d", //235295 - "c85dcffb16d5a45bd239021ad33443414d60224760f11d535ae2063e5709efee", //235296 - // all vouts banned - "c4ea1462c207547cd6fb6a4155ca6d042b22170d29801a465db5c09fec55b19d", //246748 - "305dc96d8bc23a69d3db955e03a6a87c1832673470c32fe25473a46cc473c7d1", //247204 - //"43416a0c4da6b1a5c1d375bdbe8f7dc8d44d8f60df593d3376aa8221ec66357e", // vout0 only - //"1eb295ed54c47f35cbccd7e7e40d03041f1853581da6d41102a9d8813782b6cb", - //"db121e4012222adfc841824984a2a90b7e5b018dd71307822537d58160195e43", - //"28f95b8148ac4ae6e09c7380e34422fab41d568a411e53dc94823e36a3d6f386", - //"01d8c839463bda2f2f6400ede4611357913684927a767422a8560ead1b22557c", - //"6e4980a9e1bd669f4df04732dc6f11b7773b6de88d1abcf89a6b9007d72ef9ac", - //"6cc1d0495170bc0e11fd3925297623562e529ea1336b66ea61f8a1159041aed2", - //"250875424cece9bcd98cb226b09da7671625633d6958589e3a462bad89ad87cc", // missed - //"ea8659011de52f4dac42cda12326064b7b5013b8492f88e33159884ca299aa05", // missed - //"ce567928b5490a17244167af161b1d8dd6ff753fef222fe6855d95b2278a35b3", // missed -}; - -int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts) -{ - if ( k < indallvouts ) - return(vout == 1); - else if ( k == indallvouts || k == indallvouts+1 ) - return(1); - else return(vout == 0); -} - -int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max) -{ - int32_t i; - if ( sizeof(banned_txids)/sizeof(*banned_txids) > max ) - { - fprintf(stderr,"komodo_bannedset: buffer too small %d vs %d\n",(int32_t)(sizeof(banned_txids)/sizeof(*banned_txids)),max); - StartShutdown(); - } - for (i=0; i 1 && block.vtx[txn_count-1].vout.size() > 0 && block.vtx[txn_count-1].vout[0].nValue == 5000 ) - { - /* - if ( block.vtx[txn_count-1].vin.size() == 1 && GetTransaction(block.vtx[txn_count-1].vin[0].prevout.hash,tx,hash,false) && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) - notmatched = 1; - */ - if ( block.vtx[txn_count-1].vin.size() == 1 ) { - uint256 hashNotaryProofVin = block.vtx[txn_count-1].vin[0].prevout.hash; - int fNotaryProofVinTxFound = GetTransaction(hashNotaryProofVin,tx,hash,false); - if (!fNotaryProofVinTxFound) { - // try to search in the same block - BOOST_FOREACH(const CTransaction &txInThisBlock, block.vtx) { - if (txInThisBlock.GetHash() == hashNotaryProofVin) { - fNotaryProofVinTxFound = 1; - tx = txInThisBlock; - hash = block.GetHash(); - break; - } - } - } - if ( fNotaryProofVinTxFound && block.vtx[0].vout[0].scriptPubKey == tx.vout[block.vtx[txn_count-1].vin[0].prevout.n].scriptPubKey ) - { - notmatched = 1; - } - } - } - n = block.vtx[i].vin.size(); - for (j=0; j= indallvouts) ) - { - printf("banned tx.%d being used at ht.%d txi.%d vini.%d\n",k,height,i,j); - return(-1); - } - } - } - } - } - if ( height > 0 && ASSETCHAINS_MARMARA != 0 && (height & 1) == 0 ) - { - if ( MarmaraValidateCoinbase(height,block.vtx[0]) < 0 ) - { - fprintf(stderr,"MARMARA error ht.%d constrains even height blocks to pay 100%% to CC in vout0 with opreturn\n",height); - return(-1); - } - } - // we don't want these checks in VRSC, leave it at the Sapling upgrade - if ( ASSETCHAINS_SYMBOL[0] == 0 || - ((ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1) || - NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING) ) - { - n = block.vtx[0].vout.size(); - int64_t val,prevtotal = 0; int32_t strangeout=0,overflow = 0; - total = 0; - for (i=1; i= MAX_MONEY ) - { - overflow = 1; - break; - } - if ( i > 1 && script[0] != 0x6a && val < 5000 ) - strangeout++; - total += val; - if ( total < prevtotal || (val != 0 && total == prevtotal) ) - { - overflow = 1; - break; - } - prevtotal = total; - } - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - if ( overflow != 0 || total > COIN/10 ) - { - if ( height >= activation ) - { - if ( height > 800000 ) - fprintf(stderr,">>>>>>>> <<<<<<<<<< ht.%d illegal nonz output %.8f n.%d\n",height,dstr(block.vtx[0].vout[1].nValue),n); - return(-1); - } - } - else if ( block.nBits == KOMODO_MINDIFF_NBITS && total > 0 ) // to deal with fee stealing - { - fprintf(stderr,"notary mined ht.%d with extra %.8f\n",height,dstr(total)); - if ( height > KOMODO_NOTARIES_HEIGHT1 ) - return(-1); - } - if ( strangeout != 0 || notmatched != 0 ) - { - if ( 0 && strcmp(NOTARY_PUBKEY.c_str(),"03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828") == 0 ) - fprintf(stderr,">>>>>>>>>>>>> DUST ht.%d strangout.%d notmatched.%d <<<<<<<<<\n",height,strangeout,notmatched); - if ( height > 1000000 && strangeout != 0 ) - return(-1); - } - else if ( height > 814000 ) - { - script = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; - //int32_t notary = komodo_electednotary(&num,script+1,height,0); - //if ( (-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)) < 0 ) - // fprintf(stderr, ">>>>>>> FAILED BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); - //else - // fprintf(stderr, "<<<<<<< VALID BLOCK.%d notary.%d insync.%d\n",height,notary,KOMODO_INSYNC); - return(-1 * (komodo_electednotary(&num,script+1,height,0) >= 0) * (height > 1000000)); - } - } - else - { - checktoshis = 0; - if ( (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1 ) - { - if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 ) - { - fprintf(stderr,"ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); - return(-1); - } - } - if ( height > 1 && checktoshis == 0 ) - { - checktoshis = ((uint64_t)GetBlockSubsidy(height, Params().GetConsensus()) - block.vtx[0].vout[0].nValue); - // some pools will need to change their pool fee to be (poolfee % - txfees) - //checktoshis += txn_count * 0.001; // rely on higher level validations to prevent emitting more coins than actual txfees - } - if ( height >= 2 && (overflow != 0 || total > checktoshis || strangeout != 0) ) - { - fprintf(stderr,"checkdeposit: ht.%d checktoshis %.8f overflow.%d total %.8f strangeout.%d\n",height,dstr(checktoshis),overflow,dstr(total),strangeout); - if ( strangeout != 0 ) - fprintf(stderr,">>>>>>>>>>>>> %s DUST ht.%d strangeout.%d notmatched.%d <<<<<<<<<\n",ASSETCHAINS_SYMBOL,height,strangeout,notmatched); - return(-1); - } - } - } - return(0); -} - -const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) -{ - uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; - const char *typestr = "unknown"; - if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) < 0 && opretbuf[0] != 'K' ) - { - //printf("komodo_opreturn skip %s\n",ASSETCHAINS_SYMBOL); - return("assetchain"); - } - memset(baseids,0xff,sizeof(baseids)); - memset(values,0,sizeof(values)); - memset(srcvalues,0,sizeof(srcvalues)); - memset(rmd160s,0,sizeof(rmd160s)); - memset(kmdheights,0,sizeof(kmdheights)); - memset(otherheights,0,sizeof(otherheights)); - tokomodo = (komodo_is_issuer() == 0); - if ( opretbuf[0] == 'K' && opretlen != 40 ) - { - komodo_kvupdate(opretbuf,opretlen,value); - return("kv"); - } - else if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_PAX == 0 ) - return("nopax"); - if ( opretbuf[0] == 'D' ) - { - tokomodo = 0; - if ( opretlen == 38 ) // any KMD tx - { - iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight); - memset(base,0,sizeof(base)); - PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&fiatoshis); - bitcoin_address(coinaddr,addrtype,rmd160,20); - checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,fiatoshis); - if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) != 0 ) - checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,height,base,fiatoshis); - typestr = "deposit"; - if ( 0 && strcmp("NOK",base) == 0 ) - { - printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); - printf("(%s) (%s) kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&txid)[i]); - printf(" <- txid.v%u ",vout); - for (i=0; i<33; i++) - printf("%02x",pubkey33[i]); - printf(" checkpubkey check %.8f v %.8f dest.(%s) kmdheight.%d height.%d\n",dstr(checktoshis),dstr(value),destaddr,kmdheight,height); - } - if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 && (kmdheight > 195000 || kmdheight <= height) ) - { - didstats = 0; - if ( komodo_paxcmp(base,kmdheight,value,checktoshis,kmdheight < 225000 ? seed : 0) == 0 ) - { - if ( (pax= komodo_paxfind(txid,vout,'D')) == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->deposited += fiatoshis; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p deposited %s += %.8f kmdheight.%d %.8f\n",basesp,base,dstr(fiatoshis),kmdheight,dstr(value)); - } else printf("cant get stateptr.(%s)\n",base); - komodo_gateway_deposit(coinaddr,value,base,fiatoshis,rmd160,txid,vout,'D',kmdheight,height,(char *)"KMD",0); - } - if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) - { - pax->height = kmdheight; - pax->validated = value; - pax->komodoshis = value; - pax->fiatoshis = fiatoshis; - if ( didstats == 0 && pax->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->deposited += fiatoshis; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p depositedB %s += %.8f/%.8f kmdheight.%d/%d %.8f/%.8f\n",basesp,base,dstr(fiatoshis),dstr(pax->fiatoshis),kmdheight,pax->height,dstr(value),dstr(pax->komodoshis)); - } - } // - if ( didstats != 0 ) - pax->didstats = 1; - if ( (pax2= komodo_paxfind(txid,vout,'I')) != 0 ) - { - pax2->fiatoshis = pax->fiatoshis; - pax2->komodoshis = pax->komodoshis; - pax->marked = pax2->marked = pax->height; - pax2->height = pax->height = height; - if ( pax2->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->issued += pax2->fiatoshis; - pax2->didstats = 1; - if ( 0 && strcmp(base,"USD") == 0 ) - printf("########### %p issueda %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,base,dstr(pax2->fiatoshis),pax2->height,dstr(pax2->komodoshis),pax2->otherheight,height); - } - } - } - } - } - else - { - if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 ) - pax->marked = checktoshis; - if ( kmdheight > 238000 && (kmdheight > 214700 || strcmp(base,ASSETCHAINS_SYMBOL) == 0) ) //seed != 0 && - printf("pax %s deposit %.8f rejected kmdheight.%d %.8f KMD check %.8f seed.%llu\n",base,dstr(fiatoshis),kmdheight,dstr(value),dstr(checktoshis),(long long)seed); - } - } //else printf("[%s] %s paxdeposit height.%d vs kmdheight.%d\n",ASSETCHAINS_SYMBOL,base,height,kmdheight); - } //else printf("unsupported size.%d for opreturn D\n",opretlen); - } - else if ( opretbuf[0] == 'I' ) - { - tokomodo = 0; - if ( strncmp((char *)"KMD",(char *)&opretbuf[opretlen-4],3) != 0 && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 ) - { - if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,0)) > 0 ) - { - for (i=0; itype = opretbuf[0]; - strcpy(pax->source,(char *)&opretbuf[opretlen-4]); - if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 && pax2->fiatoshis != 0 && pax2->komodoshis != 0 ) - { - // realtime path? - pax->fiatoshis = pax2->fiatoshis; - pax->komodoshis = pax2->komodoshis; - pax->marked = pax2->marked = pax2->height; - if ( pax->didstats == 0 ) - { - if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->issued += pax->fiatoshis; - pax->didstats = 1; - pax->height = pax2->height; - pax->otherheight = height; - if ( 1 && strcmp(CURRENCIES[baseids[i]],"USD") == 0 ) - printf("########### %p issuedb %s += %.8f kmdheight.%d %.8f other.%d [%d]\n",basesp,CURRENCIES[baseids[i]],dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight,height); - } - } - } - } - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'I',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'D',height)) != 0 ) - komodo_paxdelete(pax); - } - } //else printf("opreturn none issued?\n"); - } - } - else if ( height < 236000 && opretbuf[0] == 'W' && strncmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4],3) == 0 )//&& opretlen >= 38 ) - { - if ( komodo_baseid((char *)&opretbuf[opretlen-4]) >= 0 && strcmp(ASSETCHAINS_SYMBOL,(char *)&opretbuf[opretlen-4]) == 0 ) - { - for (i=0; i (%s) len.%d\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr,opretlen); - didstats = 0; - //if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 ) - { - if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) ) - { - if ( (basesp= komodo_stateptrget(base)) != 0 ) - { - basesp->withdrawn += value; - didstats = 1; - if ( 0 && strcmp(base,ASSETCHAINS_SYMBOL) == 0 ) - printf("########### %p withdrawn %s += %.8f check %.8f\n",basesp,base,dstr(value),dstr(checktoshis)); - } - if ( 0 && strcmp(base,"RUB") == 0 && (pax == 0 || pax->approved == 0) ) - printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height); - } - komodo_gateway_deposit(coinaddr,0,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0); - if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 ) - { - pax->type = opretbuf[0]; - strcpy(pax->source,base); - strcpy(pax->symbol,"KMD"); - pax->height = kmdheight; - pax->otherheight = height; - pax->komodoshis = komodoshis; - } - } // else printf("withdraw %s paxcmp ht.%d %d error value %.8f -> %.8f vs %.8f\n",base,kmdheight,height,dstr(value),dstr(komodoshis),dstr(checktoshis)); - // need to allocate pax - } - else if ( height < 236000 && tokomodo != 0 && opretbuf[0] == 'A' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - tokomodo = 1; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - { - for (i=0; i 0 ) - { - for (i=0; isymbol); - printf("override neg1 with (%s)\n",pax->symbol); - } - if ( baseids[i] < 0 ) - continue; - } - didstats = 0; - seed = 0; - checktoshis = komodo_paxprice(&seed,kmdheights[i],CURRENCIES[baseids[i]],(char *)"KMD",(uint64_t)values[i]); - //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)values[i]/COIN,(double)srcvalues[i]/COIN,(double)checktoshis/COIN); - if ( srcvalues[i] == checktoshis ) - { - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) - { - bitcoin_address(coinaddr,60,&rmd160s[i*20],20); - komodo_gateway_deposit(coinaddr,srcvalues[i],CURRENCIES[baseids[i]],values[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]); - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 ) - printf("unexpected null pax for approve\n"); - else pax->validated = checktoshis; - if ( (pax2= komodo_paxfind(txids[i],vouts[i],'W')) != 0 ) - pax2->approved = kmdheights[i]; - komodo_paxmark(height,txids[i],vouts[i],'W',height); - //komodo_paxmark(height,txids[i],vouts[i],'A',height); - if ( values[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->approved += values[i]; - didstats = 1; - //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); - } - //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i])); - } - else if ( pax->didstats == 0 && srcvalues[i] != 0 ) - { - if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->approved += values[i]; - didstats = 1; - //printf("pax.%p ########### %p approved %s += %.8f -> %.8f/%.8f kht.%d %d\n",pax,basesp,CURRENCIES[baseids[i]],dstr(values[i]),dstr(srcvalues[i]),dstr(checktoshis),kmdheights[i],otherheights[i]); - } - } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]); - if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 ) - { - pax->type = opretbuf[0]; - pax->approved = kmdheights[i]; - pax->validated = checktoshis; - if ( didstats != 0 ) - pax->didstats = 1; - //if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) - //printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax); - } - } - } - } //else printf("n.%d from opreturns\n",n); - //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal())); - } - else if ( height < 236000 && opretbuf[0] == 'X' && ASSETCHAINS_SYMBOL[0] == 0 ) - { - tokomodo = 1; - if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,1)) > 0 ) - { - for (i=0; itype = opretbuf[0]; - if ( height < 121842 ) // fields got switched around due to legacy issues and approves - value = srcvalues[i]; - else value = values[i]; - if ( baseids[i] >= 0 && value != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 ) - { - basesp->redeemed += value; - pax->didstats = 1; - if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 ) - printf("ht.%d %.8f ########### %p redeemed %s += %.8f %.8f kht.%d ht.%d\n",height,dstr(value),basesp,CURRENCIES[baseids[i]],dstr(value),dstr(srcvalues[i]),kmdheights[i],otherheights[i]); - } - } - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'W',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'A',height)) != 0 ) - komodo_paxdelete(pax); - if ( (pax= komodo_paxmark(height,txids[i],vouts[i],'X',height)) != 0 ) - komodo_paxdelete(pax); - } - } //else printf("komodo_issued_opreturn returned %d\n",n); - } - return(typestr); -} - -int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); - -void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest) -{ - uint8_t func; long lastK,lastT,lastN,lastV,fpos,lastfpos; int32_t i,count,doissue,iter,numn,numv,numN,numV,numR; uint32_t tmp,prevpos100,offset; - count = numR = numN = numV = numn = numv = 0; - lastK = lastT = lastN = lastV = -1; - for (iter=0; iter<2; iter++) - { - for (lastfpos=fpos=prevpos100=i=0; i> 8); - fpos = prevpos100 + offset; - if ( lastfpos >= datalen || (filedata[lastfpos] != func && func != 0) ) - printf("i.%d/n.%d lastfpos.%ld >= datalen.%ld or [%d] != func.%d\n",i,n,lastfpos,datalen,filedata[lastfpos],func); - else if ( iter == 0 ) - { - switch ( func ) - { - default: case 'P': case 'U': case 'D': - inds[i] &= 0xffffff00; - break; - case 'K': - lastK = lastfpos; - inds[i] &= 0xffffff00; - break; - case 'T': - lastT = lastfpos; - inds[i] &= 0xffffff00; - break; - case 'N': - lastN = lastfpos; - numN++; - break; - case 'V': - lastV = lastfpos; - numV++; - break; - case 'R': - numR++; - break; - } - } - else - { - doissue = 0; - if ( func == 'K' ) - { - if ( lastK == lastfpos ) - doissue = 1; - } - else if ( func == 'T' ) - { - if ( lastT == lastfpos ) - doissue = 1; - } - else if ( func == 'N' ) - { - if ( numn > numN-128 ) - doissue = 1; - numn++; - } - else if ( func == 'V' ) - { - if ( KOMODO_PAX != 0 && numv > numV-1440 ) - doissue = 1; - numv++; - } - else if ( func == 'R' ) - doissue = 1; - if ( doissue != 0 ) - { - //printf("issue %c total.%d lastfpos.%ld\n",func,count,lastfpos); - komodo_parsestatefiledata(sp,filedata,&lastfpos,datalen,symbol,dest); - count++; - } - } - } - lastfpos = fpos; - } - } - printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); - /*else if ( func == 'K' ) // KMD height: stop after 1st - else if ( func == 'T' ) // KMD height+timestamp: stop after 1st - - else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; - else if ( func == 'V' ) // price feed: can stop after 1440+ - else if ( func == 'R' ) // opreturn:*/ -} +int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo); + +int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); + +int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); + +int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); // verify above block is valid pax pricing + +/*** + * handle an opreturn + * @param height the height + * @param value the value + * @param opretbuf the buffer + * @param opretlen the length of the buffer + * @param txid + * @param vout + * @param source + * @returns result (i.e. "unknown", "assetchain", "kv", ect. + */ +const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source); + +void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest); /**** * Load file contents into buffer @@ -1265,43 +81,7 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ * @param allocsizep the buffer size allocated * @returns the file contents */ -void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) -{ - FILE *fp; - long filesize,buflen = *allocsizep; - uint8_t *buf = *bufp; - *lenp = 0; - if ( (fp= fopen(fname,"rb")) != 0 ) - { - fseek(fp,0,SEEK_END); - filesize = ftell(fp); - if ( filesize == 0 ) - { - fclose(fp); - *lenp = 0; - printf("OS_loadfile null size.(%s)\n",fname); - return(0); - } - if ( filesize > buflen ) - { - *allocsizep = filesize; - *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); - } - rewind(fp); - if ( buf == 0 ) - printf("Null buf ???\n"); - else - { - if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) - printf("error reading filesize.%ld\n",(long)filesize); - buf[filesize] = 0; - } - fclose(fp); - *lenp = filesize; - //printf("loaded.(%s)\n",buf); - } //else printf("OS_loadfile couldnt load.(%s)\n",fname); - return(buf); -} +void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); /*** * Get file contents @@ -1309,79 +89,11 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) * @param fname the file name * @returns the data from the file */ -uint8_t *OS_fileptr(long *allocsizep,char *fname) -{ - long filesize = 0; // the size of the file - uint8_t *buf = 0; // a pointer to the buffer - void *retptr; // the return pointer (points to buf) - *allocsizep = 0; - retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); - return((uint8_t *)retptr); -} - -long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest) -{ - FILE *fp; long fsize,lastfpos=0,fpos=0; uint8_t *inds,func; int32_t i,n; uint32_t offset,tmp,prevpos100 = 0; - *indcounterp = *prevpos100p = 0; - if ( (inds= OS_fileptr(&fsize,indfname)) != 0 ) - { - lastfpos = 0; - fprintf(stderr,"inds.%p validate %s fsize.%ld datalen.%ld n.%d lastfpos.%ld\n",inds,indfname,fsize,datalen,(int32_t)(fsize / sizeof(uint32_t)),lastfpos); - if ( (fsize % sizeof(uint32_t)) == 0 ) - { - n = (int32_t)(fsize / sizeof(uint32_t)); - for (i=0; i n-10 ) - printf("%d: tmp.%08x [%c] prevpos100.%u\n",i,tmp,tmp&0xff,prevpos100); - if ( (i % 100) == 0 ) - prevpos100 = tmp; - else - { - func = (tmp & 0xff); - offset = (tmp >> 8); - fpos = prevpos100 + offset; - if ( lastfpos >= datalen || filedata[lastfpos] != func ) - { - printf("validate.%d error (%u %d) prev100 %u -> fpos.%ld datalen.%ld [%d] (%c) vs (%c) lastfpos.%ld\n",i,offset,func,prevpos100,fpos,datalen,lastfpos < datalen ? filedata[lastfpos] : -1,func,filedata[lastfpos],lastfpos); - return(-1); - } - } - lastfpos = fpos; - } - *indcounterp = n; - *prevpos100p = prevpos100; - if ( sp != 0 ) - komodo_stateind_set(sp,(uint32_t *)inds,n,filedata,fpos,symbol,dest); - //printf("free inds.%p %s validated[%d] fpos.%ld datalen.%ld, offset %ld vs fsize.%ld\n",inds,indfname,i,fpos,datalen,i * sizeof(uint32_t),fsize); - free(inds); - return(fpos); - } else printf("wrong filesize %s %ld\n",indfname,fsize); - } - free(inds); - fprintf(stderr,"indvalidate return -1\n"); - return(-1); -} - -long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp) -{ - uint32_t tmp; - if ( indfp != 0 ) - { - tmp = ((uint32_t)(newfpos - *prevpos100p) << 8) | (func & 0xff); - if ( ftell(indfp)/sizeof(uint32_t) != *indcounterp ) - printf("indfp fpos %ld -> ind.%ld vs counter.%u\n",ftell(indfp),ftell(indfp)/sizeof(uint32_t),*indcounterp); - //fprintf(stderr,"ftell.%ld indcounter.%u lastfpos.%ld newfpos.%ld func.%02x\n",ftell(indfp),*indcounterp,lastfpos,newfpos,func); - fwrite(&tmp,1,sizeof(tmp),indfp), (*indcounterp)++; - if ( (*indcounterp % 100) == 0 ) - { - *prevpos100p = (uint32_t)newfpos; - fwrite(prevpos100p,1,sizeof(*prevpos100p),indfp), (*indcounterp)++; - } - } - return(newfpos); -} +uint8_t *OS_fileptr(long *allocsizep,char *fname); + +long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest); + +long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp); /*** * Initialize state from the filesystem @@ -1391,1399 +103,98 @@ long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long * @param dest * @returns -1 on error, 1 on success */ -int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest) -{ - FILE *indfp; // an index file that will be created - char indfname[1024]; // the filename of the index file - uint8_t *filedata; // data read from the file fname - long validated=-1; // not used - long datalen; // length of the data read from fname plus a little more - long fpos; // where we are reading in filedata - long lastfpos; // not used - uint32_t tmp; // not used - uint32_t prevpos100; // position to be written in index file - uint32_t indcounter; // position within index file - uint32_t starttime = (uint32_t)time(NULL); - int32_t func; // record type - int32_t finished = 0; // boolean, true if file has been read successfully - - safecopy(indfname,fname,sizeof(indfname)-4); // truncate 4 characters from filename - strcat(indfname,".ind"); - - if ( (filedata= OS_fileptr(&datalen,fname)) != 0 ) - { - if ( 1 )//datalen >= (1LL << 32) || GetArg("-genind",0) != 0 || (validated= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) - { - lastfpos = fpos = 0; - indcounter = prevpos100 = 0; - if ( (indfp= fopen(indfname,"wb")) != 0 ) - fwrite(&prevpos100,1,sizeof(prevpos100),indfp), indcounter++; - fprintf(stderr,"processing %s %ldKB, validated.%ld\n",fname,datalen/1024,validated); - while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) - { - lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); - } - if ( indfp != 0 ) - { - fclose(indfp); - if ( (fpos= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) - printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); - else printf("%s validated fpos.%ld\n",indfname,fpos); - } - finished = 1; - fprintf(stderr,"took %d seconds to process %s %ldKB\n",(int32_t)(time(NULL)-starttime),fname,datalen/1024); - } - else if ( validated > 0 ) - { - if ( (indfp= fopen(indfname,"rb+")) != 0 ) - { - lastfpos = fpos = validated; - fprintf(stderr,"datalen.%ld validated %ld -> indcounter %u, prevpos100 %u offset.%d\n",datalen,validated,indcounter,prevpos100,(int32_t)(indcounter * sizeof(uint32_t))); - if ( fpos < datalen ) - { - fseek(indfp,indcounter * sizeof(uint32_t),SEEK_SET); - if ( ftell(indfp) == indcounter * sizeof(uint32_t) ) - { - while ( (func= komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest)) >= 0 ) - { - lastfpos = komodo_indfile_update(indfp,&prevpos100,lastfpos,fpos,func,&indcounter); - if ( lastfpos != fpos ) - fprintf(stderr,"unexpected lastfpos.%ld != %ld\n",lastfpos,fpos); - } - } - fclose(indfp); - } - if ( komodo_stateind_validate(sp,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest) < 0 ) - printf("unexpected komodostate.ind validate failure %s datalen.%ld\n",indfname,datalen); - else - { - printf("%s validated updated from validated.%ld to %ld new.[%ld] -> indcounter %u, prevpos100 %u offset.%ld | elapsed %d seconds\n",indfname,validated,fpos,fpos-validated,indcounter,prevpos100,indcounter * sizeof(uint32_t),(int32_t)(time(NULL) - starttime)); - finished = 1; - } - } - } else printf("komodo_faststateinit unexpected case\n"); - free(filedata); - return(finished == 1); - } - return(-1); -} - -uint64_t komodo_interestsum(); - -void komodo_passport_iteration() -{ - static long lastpos[34]; static char userpass[33][1024]; static uint32_t lasttime,callcounter,lastinterest; - int32_t maxseconds = 10; - FILE *fp; uint8_t *filedata; long fpos,datalen,lastfpos; int32_t baseid,limit,n,ht,isrealtime,expired,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; uint32_t buf[3],starttime; uint64_t RTmask = 0; //CBlockIndex *pindex; - expired = 0; - while ( 0 && KOMODO_INITDONE == 0 ) - { - fprintf(stderr,"[%s] PASSPORT iteration waiting for KOMODO_INITDONE\n",ASSETCHAINS_SYMBOL); - sleep(3); - } - if ( komodo_chainactive_timestamp() > lastinterest ) - { - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - komodo_interestsum(); - //komodo_longestchain(); - lastinterest = komodo_chainactive_timestamp(); - } - refsp = komodo_stateptr(symbol,dest); - if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDCC") == 0 ) - { - refid = 33; - limit = 10000000; - jumblr_iteration(); - } - else - { - limit = 10000000; - refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0 - if ( refid == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - return; - } - } - /*if ( KOMODO_PAX == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - return; - }*/ - starttime = (uint32_t)time(NULL); - if ( callcounter++ < 1 ) - limit = 10000; - lasttime = starttime; - for (baseid=32; baseid>=0; baseid--) - { - if ( time(NULL) >= starttime+maxseconds ) - break; - sp = 0; - isrealtime = 0; - base = (char *)CURRENCIES[baseid]; - //printf("PASSPORT %s baseid+1 %d refid.%d\n",ASSETCHAINS_SYMBOL,baseid+1,refid); - if ( baseid+1 != refid ) // only need to import state from a different coin - { - if ( baseid == 32 ) // only care about KMD's state - { - refsp->RTmask &= ~(1LL << baseid); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate"); - komodo_nameset(symbol,dest,base); - sp = komodo_stateptrget(symbol); - n = 0; - if ( lastpos[baseid] == 0 && (filedata= OS_fileptr(&datalen,fname)) != 0 ) - { - fpos = 0; - fprintf(stderr,"%s processing %s %ldKB\n",ASSETCHAINS_SYMBOL,fname,datalen/1024); - while ( komodo_parsestatefiledata(sp,filedata,&fpos,datalen,symbol,dest) >= 0 ) - lastfpos = fpos; - fprintf(stderr,"%s took %d seconds to process %s %ldKB\n",ASSETCHAINS_SYMBOL,(int32_t)(time(NULL)-starttime),fname,datalen/1024); - lastpos[baseid] = lastfpos; - free(filedata), filedata = 0; - datalen = 0; - } - else if ( (fp= fopen(fname,"rb")) != 0 && sp != 0 ) - { - fseek(fp,0,SEEK_END); - //fprintf(stderr,"couldnt OS_fileptr(%s), freading %ldKB\n",fname,ftell(fp)/1024); - if ( ftell(fp) > lastpos[baseid] ) - { - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - printf("%s passport refid.%d %s fname.(%s) base.%s %ld %ld\n",ASSETCHAINS_SYMBOL,refid,symbol,fname,base,ftell(fp),lastpos[baseid]); - fseek(fp,lastpos[baseid],SEEK_SET); - while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 && n < limit ) - { - if ( n == limit-1 ) - { - if ( time(NULL) < starttime+maxseconds ) - n = 0; - else - { - //printf("expire passport loop %s -> %s at %ld\n",ASSETCHAINS_SYMBOL,base,lastpos[baseid]); - expired++; - } - } - n++; - } - lastpos[baseid] = ftell(fp); - if ( 0 && lastpos[baseid] == 0 && strcmp(symbol,"KMD") == 0 ) - printf("from.(%s) lastpos[%s] %ld isrt.%d\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid],komodo_isrealtime(&ht)); - } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp)); - fclose(fp); - } else fprintf(stderr,"load error.(%s) %p\n",fname,sp); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"rb")) != 0 ) - { - if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) ) - { - sp->CURRENT_HEIGHT = buf[0]; - if ( buf[0] != 0 && buf[0] >= buf[1] && buf[2] > time(NULL)-60 ) - { - isrealtime = 1; - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - } - else if ( KOMODO_PAX != 0 && (time(NULL)-buf[2]) > 60 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"[%s]: %s not RT %u %u %d\n",ASSETCHAINS_SYMBOL,base,buf[0],buf[1],(int32_t)(time(NULL)-buf[2])); - } //else fprintf(stderr,"%s size error RT\n",base); - fclose(fp); - } //else fprintf(stderr,"%s open error RT\n",base); - } - } - else - { - refsp->RTmask &= ~(1LL << baseid); - komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime"); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - buf[0] = (uint32_t)chainActive.LastTip()->GetHeight(); - buf[1] = (uint32_t)komodo_longestchain(); - if ( buf[0] != 0 && buf[0] == buf[1] ) - { - buf[2] = (uint32_t)time(NULL); - RTmask |= (1LL << baseid); - memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1])); - if ( refid != 0 ) - memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0])); - } - if ( fwrite(buf,1,sizeof(buf),fp) != sizeof(buf) ) - fprintf(stderr,"[%s] %s error writing realtime\n",ASSETCHAINS_SYMBOL,base); - fclose(fp); - } else fprintf(stderr,"%s create error RT\n",base); - } - if ( sp != 0 && isrealtime == 0 ) - refsp->RTbufs[0][2] = 0; - } - //komodo_paxtotal(); // calls komodo_isrealtime(), which calls komodo_longestchain() - refsp->RTmask |= RTmask; - if ( expired == 0 && KOMODO_PASSPORT_INITDONE == 0 ) - { - KOMODO_PASSPORT_INITDONE = 1; - printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); - } -} - - -extern std::vector Mineropret; // opreturn data set by the data gathering code -#define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% -#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR -#define KOMODO_LOCALPRICE_CACHESIZE 13 -#define KOMODO_MAXPRICES 2048 -#define PRICES_SMOOTHWIDTH 1 - -#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) - -const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) -// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" -const char *Forex[] = -{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" -}; // must be in ECB list - -struct komodo_extremeprice -{ - uint256 blockhash; - uint32_t pricebits,timestamp; - int32_t height; - int16_t dir,ind; -} ExtremePrice; - -struct komodo_priceinfo -{ - FILE *fp; - char symbol[64]; -} PRICES[KOMODO_MAXPRICES]; - -uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; -int64_t PriceMult[KOMODO_MAXPRICES]; -int32_t komodo_cbopretsize(uint64_t flags); +int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest); + +void komodo_passport_iteration(); + +void komodo_PriceCache_shift(); -void komodo_PriceCache_shift() -{ - int32_t i; - for (i=KOMODO_LOCALPRICE_CACHESIZE-1; i>0; i--) - memcpy(PriceCache[i],PriceCache[i-1],sizeof(PriceCache[i])); - memcpy(PriceCache[0],Mineropret.data(),Mineropret.size()); -} - -int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block) -{ - CTransaction tx; int32_t numvouts; std::vector vopret; - tx = block->vtx[0]; - numvouts = (int32_t)tx.vout.size(); - GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); - if ( vopret.size() >= PRICES_SIZEBIT0 ) - { - if ( seedp != 0 ) - memcpy(seedp,&block->hashMerkleRoot,sizeof(*seedp)); - memcpy(heightbits,vopret.data(),vopret.size()); - return((int32_t)(vopret.size()/sizeof(uint32_t))); - } - return(-1); -} +int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block); // komodo_heightpricebits() extracts the price data in the coinbase for nHeight -int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight) -{ - CBlockIndex *pindex; CBlock block; - if ( seedp != 0 ) - *seedp = 0; - if ( (pindex= komodo_chainactive(nHeight)) != 0 ) - { - if ( komodo_blockload(block,pindex) == 0 ) - { - return(_komodo_heightpricebits(seedp,heightbits,&block)); - } - } - fprintf(stderr,"couldnt get pricebits for %d\n",nHeight); - return(-1); -} +int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight); /* komodo_pricenew() is passed in a reference price, the change tolerance and the proposed price. it needs to return a clipped price if it is too big and also set a flag if it is at or above the limit */ -uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance) -{ - uint64_t highprice,lowprice; - if ( refprice < 2 ) - return(0); - highprice = ((uint64_t)refprice * (COIN + tolerance)) / COIN; // calc highest acceptable price - lowprice = ((uint64_t)refprice * (COIN - tolerance)) / COIN; // and lowest - if ( highprice == refprice ) - highprice++; - if ( lowprice == refprice ) - lowprice--; - if ( price >= highprice ) - { - //fprintf(stderr,"high %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); - if ( price > highprice ) // return non-zero only if we violate the tolerance - { - *maxflagp = 2; - return(highprice); - } - *maxflagp = 1; - } - else if ( price <= lowprice ) - { - //fprintf(stderr,"low %u vs h%llu l%llu tolerance.%llu\n",price,(long long)highprice,(long long)lowprice,(long long)tolerance); - if ( price < lowprice ) - { - *maxflagp = -2; - return(lowprice); - } - *maxflagp = -1; - } - return(0); -} +uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance); // komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance -int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance) -{ - int32_t i; uint32_t newprice; - for (i=1; i newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,maxflags[i]); - return(-1); - } - } - return(0); -} +int32_t komodo_pricecmp(int32_t nHeight, char *maxflags, uint32_t *pricebitsA, uint32_t *pricebitsB, int32_t begin, int32_t end, int64_t tolerance); // komodo_priceclamp() clamps any price that is beyond tolerance -int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance) -{ - int32_t i; uint32_t newprice; char maxflags[KOMODO_MAXPRICES]; - memset(maxflags,0,sizeof(maxflags)); - for (i=1; i %u\n",i,n,refprices[i],pricebits[i],newprice); - pricebits[i] = newprice; - } - } - return(0); -} +int32_t komodo_priceclamp(uint32_t *pricebits, uint32_t *refprices, int32_t begin, int32_t end, int64_t tolerance); // komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight -CScript komodo_mineropret(int32_t nHeight) -{ - CScript opret; char maxflags[KOMODO_MAXPRICES]; uint32_t pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES]; int32_t maxflag,i,n,numzero=0; - if ( Mineropret.size() >= PRICES_SIZEBIT0 ) - { - n = (int32_t)(Mineropret.size() / sizeof(uint32_t)); - numzero = 1; - while ( numzero > 0 ) - { - memcpy(pricebits,Mineropret.data(),Mineropret.size()); - for (i=numzero=0; i 0 ) - { - memcpy(pricebits,Mineropret.data(),Mineropret.size()); - memset(maxflags,0,sizeof(maxflags)); - if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_ERRORRATE) < 0 ) - { - // if the new prices are outside tolerance, update Mineropret with clamped prices - komodo_priceclamp(n,pricebits,prevbits,PRICES_ERRORRATE); - //fprintf(stderr,"update Mineropret to clamped prices\n"); - memcpy(Mineropret.data(),pricebits,Mineropret.size()); - } - } - int32_t i; - for (i=0; i vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; - now = (uint32_t)time(NULL); - if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) - { - bhash = block->GetHash(); - GetOpReturnData(scriptPubKey,vopret); - if ( vopret.size() >= PRICES_SIZEBIT0 ) - { - n = (int32_t)(vopret.size() / sizeof(uint32_t)); - memcpy(pricebits,vopret.data(),Mineropret.size()); - memset(maxflags,0,sizeof(maxflags)); - if ( nHeight > 2 ) - { - prevtime = previndex->nTime; - lag = (int32_t)(now - pricebits[0]); - lag2 = (int32_t)(pricebits[0] - prevtime); - lag3 = (int32_t)(block->nTime - pricebits[0]); - if ( lag < -60 ) // avoid data from future - { - fprintf(stderr,"A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); - return(-1); - } - if ( lag2 < -60 ) //testchain_exemption ) // must be close to last block timestamp - { - fprintf(stderr,"B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3,ASSETCHAINS_BLOCKTIME,lag2<-ASSETCHAINS_BLOCKTIME); - if ( nHeight > testchain_exemption ) - return(-1); - } - if ( lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME ) - { - fprintf(stderr,"C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); - if ( nHeight > testchain_exemption ) - return(-1); - } - btcusd = (double)pricebits[1]/10000; - btcgbp = (double)pricebits[2]/10000; - btceur = (double)pricebits[3]/10000; - fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2); - if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 ) - { - if ( nHeight < testchain_exemption ) - { - for (i=0; i= PRICES_SIZEBIT0 ) - { - memcpy(localbits,Mineropret.data(),Mineropret.size()); - if ( nHeight < testchain_exemption ) - { - for (i=0; i 0 && localbits[i] < prevbits[i] ) - { - if ( iter == 0 ) - break; - // second iteration checks recent prices to see if within local volatility - for (j=0; j= prevbits[i] ) - { - fprintf(stderr,"i.%d within recent localprices[%d] %u >= %u\n",i,j,PriceCache[j][i],prevbits[i]); - break; - } - if ( j == KOMODO_LOCALPRICE_CACHESIZE ) - { - komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]); - break; - } - } - else if ( maxflag < 0 && localbits[i] > prevbits[i] ) - { - if ( iter == 0 ) - break; - for (j=0; jnTime,bhash,i,prevbits[i]); - break; - } - } - } - } - if ( i != n ) - { - if ( iter == 0 ) - { - fprintf(stderr,"force update prices\n"); - komodo_cbopretupdate(1); - memcpy(localbits,Mineropret.data(),Mineropret.size()); - } else return(-1); - } - } - } - } - if ( bhash == ExtremePrice.blockhash ) - { - fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime); - memset(&ExtremePrice,0,sizeof(ExtremePrice)); - } - return(0); - } else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]); - return(-1); - } - return(0); -} - -char *nonportable_path(char *str) -{ - int32_t i; - for (i=0; str[i]!=0; i++) - if ( str[i] == '/' ) - str[i] = '\\'; - return(str); -} - -char *portable_path(char *str) -{ -#ifdef _WIN32 - return(nonportable_path(str)); -#else -#ifdef __PNACL - /*int32_t i,n; - if ( str[0] == '/' ) - return(str); - else - { - n = (int32_t)strlen(str); - for (i=n; i>0; i--) - str[i] = str[i-1]; - str[0] = '/'; - str[n+1] = 0; - }*/ -#endif - return(str); -#endif -} - -void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) -{ - FILE *fp; - long filesize,buflen = *allocsizep; - uint8_t *buf = *bufp; - *lenp = 0; - if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) - { - fseek(fp,0,SEEK_END); - filesize = ftell(fp); - if ( filesize == 0 ) - { - fclose(fp); - *lenp = 0; - //printf("loadfile null size.(%s)\n",fname); - return(0); - } - if ( filesize > buflen ) - { - *allocsizep = filesize; - *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); - } - rewind(fp); - if ( buf == 0 ) - printf("Null buf ???\n"); - else - { - if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) - printf("error reading filesize.%ld\n",(long)filesize); - buf[filesize] = 0; - } - fclose(fp); - *lenp = filesize; - //printf("loaded.(%s)\n",buf); - } //else printf("OS_loadfile couldnt load.(%s)\n",fname); - return(buf); -} - -void *filestr(long *allocsizep,char *_fname) -{ - long filesize = 0; char *fname,*buf = 0; void *retptr; - *allocsizep = 0; - fname = (char *)malloc(strlen(_fname)+1); - strcpy(fname,_fname); - retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); - free(fname); - return(retptr); -} - -cJSON *send_curl(char *url,char *fname) -{ - long fsize; char curlstr[1024],*jsonstr; cJSON *json=0; - sprintf(curlstr,"wget -q \"%s\" -O %s",url,fname); - if ( system(curlstr) == 0 ) - { - if ( (jsonstr= (char *)filestr((long *)&fsize,fname)) != 0 ) - { - json = cJSON_Parse(jsonstr); - free(jsonstr); - } - } - return(json); -} +The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data. -// get_urljson just returns the JSON returned by the URL using issue_curl +*/ +int32_t komodo_opretvalidate(const CBlock *block, CBlockIndex * const previndex, int32_t nHeight, CScript scriptPubKey); +char *nonportable_path(char *str); -/* -const char *Techstocks[] = -{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN" -}; -const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; +char *portable_path(char *str); -const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; -*/ +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); + +void *filestr(long *allocsizep,char *_fname); -cJSON *get_urljson(char *url) -{ - char *jsonstr; cJSON *json = 0; - if ( (jsonstr= issue_curl(url)) != 0 ) - { - //fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr); - json = cJSON_Parse(jsonstr); - free(jsonstr); - } - return(json); -} - -int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector symbols) -{ - char url[32768],*symbol,*timestr; cJSON *json,*obj; int32_t i,n=0,retval=-1; uint32_t uprice,timestamp; - sprintf(url,"https://api.iextrading.com/1.0/tops/last?symbols=%s",GetArg("-ac_stocks","").c_str()); - fprintf(stderr,"url.(%s)\n",url); - if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"iex")) != 0 ) // - { - fprintf(stderr,"stocks.(%s)\n",jprint(json,0)); - if ( (n= cJSON_GetArraySize(json)) > 0 ) - { - retval = n; - for (i=0; i now+60 || timestamp < now-ASSETCHAINS_BLOCKTIME ) - { - fprintf(stderr,"time error.%d (%u vs %u)\n",timestamp-now,timestamp,now); - retval = -1; - }*/ - if ( symbols[i] != symbol ) - { - retval = -1; - fprintf(stderr,"MISMATCH."); - } - fprintf(stderr,"(%s %u) ",symbol,uprice); - } - } - fprintf(stderr,"numstocks.%d\n",n); - } - //https://api.iextrading.com/1.0/tops/last?symbols=AAPL -> [{"symbol":"AAPL","price":198.63,"size":100,"time":1555092606076}] - free_json(json); - } - return(retval); -} - -uint32_t get_dailyfx(uint32_t *prices) -{ - //{"base":"USD","rates":{"BGN":1.74344803,"NZD":1.471652701,"ILS":3.6329113924,"RUB":65.1997682296,"CAD":1.3430201462,"USD":1.0,"PHP":52.8641469068,"CHF":0.9970582992,"AUD":1.4129078267,"JPY":110.6792654662,"TRY":5.6523444464,"HKD":7.8499732573,"MYR":4.0824567659,"HRK":6.6232840078,"CZK":22.9862720628,"IDR":14267.4986628633,"DKK":6.6551078624,"NOK":8.6806917454,"HUF":285.131039401,"GBP":0.7626582278,"MXN":19.4183455161,"THB":31.8702085933,"ISK":122.5708682475,"ZAR":14.7033339276,"BRL":3.9750401141,"SGD":1.3573720806,"PLN":3.8286682118,"INR":69.33187734,"KRW":1139.1602781244,"RON":4.2423783206,"CNY":6.7387234801,"SEK":9.3385630237,"EUR":0.8914244963},"date":"2019-03-28"} - char url[512],*datestr; cJSON *json,*rates; int32_t i; uint32_t datenum=0,price = 0; - sprintf(url,"https://api.openrates.io/latest?base=USD"); - if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"dailyfx")) != 0 ) - { - if ( (rates= jobj(json,(char *)"rates")) != 0 ) - { - for (i=0; i strvec) -{ - int32_t i,errs=0; uint32_t price; char *symbol; - for (i=0; i 333 ) // for debug only! -// ASSETCHAINS_CBOPRET = 7; - size = komodo_cbopretsize(ASSETCHAINS_CBOPRET); - if ( Mineropret.size() < size ) - Mineropret.resize(size); - size = PRICES_SIZEBIT0; - if ( (forceflag != 0 || now > lastbtc+120) && get_btcusd(pricebits) == 0 ) - { - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(PriceCache[0],pricebits,PRICES_SIZEBIT0); - flags |= 1; - } - if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) - { - if ( now > lasttime+3600*5 || forexprices[0] == 0 ) // cant assume timestamp is valid for forex price as it is a daily weekday changing thing anyway. - { - get_dailyfx(forexprices); - if ( flags == 0 ) - komodo_PriceCache_shift(); - flags |= 2; - memcpy(&PriceCache[0][size/sizeof(uint32_t)],forexprices,sizeof(forexprices)); - } - size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t); - } - if ( (ASSETCHAINS_CBOPRET & 4) != 0 ) - { - if ( forceflag != 0 || flags != 0 ) - { - get_cryptoprices(pricebuf,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)),ASSETCHAINS_PRICES); - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,(sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t)); - flags |= 4; // very rarely we can see flags == 6 case - } - size += (sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t); - } - now = (uint32_t)time(NULL); - if ( (ASSETCHAINS_CBOPRET & 8) != 0 ) - { - if ( forceflag != 0 || flags != 0 ) - { - if ( get_stockprices(now,pricebuf,ASSETCHAINS_STOCKS) == ASSETCHAINS_STOCKS.size() ) - { - if ( flags == 0 ) - komodo_PriceCache_shift(); - memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,ASSETCHAINS_STOCKS.size() * sizeof(uint32_t)); - flags |= 8; // very rarely we can see flags == 10 case - } - } - size += (ASSETCHAINS_STOCKS.size()) * sizeof(uint32_t); - } - if ( flags != 0 ) - { - if ( (flags & 1) != 0 ) - lastbtc = now; - if ( (flags & 2) != 0 ) - lasttime = now; - memcpy(Mineropret.data(),PriceCache[0],size); - if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 ) - { - fprintf(stderr,"cmp dir.%d PriceCache[0][ExtremePrice.ind] %u >= %u ExtremePrice.pricebits\n",ExtremePrice.dir,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); - if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) - { - fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); - if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) - pindex->nStatus &= ~BLOCK_FAILED_MASK; - else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str()); - } - } - // high volatility still strands nodes so we need to check new prices to approve a stuck block - // scan list of stuck blocks (one?) and auto reconsiderblock if it changed state - - //int32_t i; for (i=0; i= KOMODO_MAXPRICES ) - return(-1); - mult = komodo_pricemult(ind); - if ( nonzprices != 0 ) - memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW); - //for (i=0; i= PRICES_DAYWINDOW ) - i = 0; - if ( (price= rawprices[i*rawskip]) == 0 ) - { - fprintf(stderr,"null rawprice.[%d]\n",i); - return(-1); - } - if ( price >= lowprice && price <= highprice ) - { - //fprintf(stderr,"%.1f ",(double)price/10000); - sum += price; - correlation++; - if ( correlation > (PRICES_DAYWINDOW>>1) ) - { - if ( nonzprices == 0 ) - return(refprice * mult); - //fprintf(stderr,"-> %.4f\n",(double)sum*mult/correlation); - //return(sum*mult/correlation); - n = 0; - i = (iter + seed) % PRICES_DAYWINDOW; - for (k=0; k= PRICES_DAYWINDOW ) - i = 0; - if ( n > (PRICES_DAYWINDOW>>1) ) - nonzprices[i] = 0; - else - { - price = rawprices[i*rawskip]; - if ( price < lowprice || price > highprice ) - nonzprices[i] = 0; - else - { - nonzprices[i] = price; - //fprintf(stderr,"(%d %u) ",i,rawprices[i*rawskip]); - n++; - } - } - } - //fprintf(stderr,"ind.%d iter.%d j.%d i.%d n.%d correlation.%d ref %llu -> %llu\n",ind,iter,j,i,n,correlation,(long long)refprice,(long long)sum/correlation); - if ( n != correlation ) - return(-1); - sum = den = n = 0; - for (i=0; i %.8f\n",(long long)firstprice,((double)(sum*mult) / den) / COIN); - return((sum * mult) / den); - } - } - } - if ( correlation > maxcorrelation ) - maxcorrelation = correlation; - } - fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice); - return(0); -} - -int64_t _pairave64(int64_t valA,int64_t valB) -{ - if ( valA != 0 && valB != 0 ) - return((valA + valB) / 2); - else if ( valA != 0 ) return(valA); - else return(valB); -} - -int64_t _pairdiff64(register int64_t valA,register int64_t valB) -{ - if ( valA != 0 && valB != 0 ) - return(valA - valB); - else return(0); -} - -int64_t balanced_ave64(int64_t buf[],int32_t i,int32_t width) -{ - register int32_t nonz,j; register int64_t sum,price; - nonz = 0; - sum = 0; - for (j=-width; j<=width; j++) - { - price = buf[i + j]; - if ( price != 0 ) - { - sum += price; - nonz++; - } - } - if ( nonz != 0 ) - sum /= nonz; - return(sum); -} - -void buf_trioave64(int64_t dest[],int64_t src[],int32_t n) -{ - register int32_t i,j,width = 3; - for (i=0; i<128; i++) - src[i] = 0; - //for (i=n-width-1; i>width; i--) - // dest[i] = balanced_ave(src,i,width); - //for (i=width; i>0; i--) - // dest[i] = balanced_ave(src,i,i); - for (i=1; i *(int64_t *)b) return 1; - else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism - return(-1); - else return(1); -} - -static void sort64(int64_t *l, int32_t llen) -{ - qsort(l,llen,sizeof(uint64_t),cmp_llu); -} - -static int revcmp_llu(const void *a, const void*b) -{ - if(*(int64_t *)a < *(int64_t *)b) return 1; - else if(*(int64_t *)a > *(int64_t *)b) return -1; - else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism - return(-1); - else return(1); -} - -static void revsort64(int64_t *l, int32_t llen) -{ - qsort(l,llen,sizeof(uint64_t),revcmp_llu); -} - -int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) -{ - int32_t i,dir=0; int64_t sum=0,nonzprice,price,halfave,thirdave,fourthave,decayprice; - if ( PRICES_DAYWINDOW < 2 ) - return(0); - for (i=0; i price ) // rising prices - sort64(buf,PRICES_DAYWINDOW); - else revsort64(buf,PRICES_DAYWINDOW); - decayprice = buf[0]; - for (i=0; i %.8f\n",halfave 0 && PRICES[0].fp != 0 && createflag != 0 ) - { - fseek(PRICES[0].fp,(2*PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH) * sizeof(uint32_t) * i,SEEK_SET); - fputc(0,PRICES[0].fp); - fflush(PRICES[0].fp); - } - fprintf(stderr,"pricesinit done i.%d num.%d numprices.%d\n",i,num,(int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t))); - if ( i != num || i != komodo_cbopretsize(ASSETCHAINS_CBOPRET)/sizeof(uint32_t) ) - { - fprintf(stderr,"fatal error opening prices files, start shutdown\n"); - StartShutdown(); - } - return(0); -} - -pthread_mutex_t pricemutex; +static int cmp_llu(const void *a, const void*b); + +static void sort64(int64_t *l, int32_t llen); + +static int revcmp_llu(const void *a, const void*b); + +static void revsort64(int64_t *l, int32_t llen); + +int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip); + +int32_t komodo_pricesinit(); // PRICES file layouts // [0] rawprice32 / timestamp @@ -2791,90 +202,8 @@ pthread_mutex_t pricemutex; // [2] 24hr ave // [3] to [7] reserved -void komodo_pricesupdate(int32_t height,CBlock *pblock) -{ - static int numprices; static uint32_t *ptr32; static int64_t *ptr64,*tmpbuf; - int32_t ind,offset,width; int64_t correlated,smoothed; uint64_t seed,rngval; uint32_t rawprices[KOMODO_MAXPRICES],buf[PRICES_MAXDATAPOINTS*2]; - width = PRICES_DAYWINDOW;//(2*PRICES_DAYWINDOW + PRICES_SMOOTHWIDTH); - if ( numprices == 0 ) - { - pthread_mutex_init(&pricemutex,0); - numprices = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t)); - ptr32 = (uint32_t *)calloc(sizeof(uint32_t),numprices * width); - ptr64 = (int64_t *)calloc(sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS); - tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW); - fprintf(stderr,"prices update: numprices.%d %p %p\n",numprices,ptr32,ptr64); - } - if ( _komodo_heightpricebits(&seed,rawprices,pblock) == numprices ) - { - //for (ind=0; ind PRICES_DAYWINDOW ) - { - fseek(PRICES[0].fp,(height-width+1) * numprices * sizeof(uint32_t),SEEK_SET); - if ( fread(ptr32,sizeof(uint32_t),width*numprices,PRICES[0].fp) == width*numprices ) - { - rngval = seed; - for (ind=1; ind 0 ) - { - fseek(PRICES[ind].fp,height * sizeof(int64_t) * PRICES_MAXDATAPOINTS,SEEK_SET); - memset(buf,0,sizeof(buf)); - buf[0] = rawprices[ind]; - buf[1] = rawprices[0]; // timestamp - memcpy(&buf[2],&correlated,sizeof(correlated)); - if ( fwrite(buf,1,sizeof(buf),PRICES[ind].fp) != sizeof(buf) ) - fprintf(stderr,"error fwrite buf for ht.%d ind.%d\n",height,ind); - else if ( height > PRICES_DAYWINDOW*2 ) - { - fseek(PRICES[ind].fp,(height-PRICES_DAYWINDOW+1) * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); - if ( fread(ptr64,sizeof(int64_t),PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS,PRICES[ind].fp) == PRICES_DAYWINDOW*PRICES_MAXDATAPOINTS ) - { - if ( (smoothed= komodo_priceave(tmpbuf,&ptr64[(PRICES_DAYWINDOW-1)*PRICES_MAXDATAPOINTS+1],-PRICES_MAXDATAPOINTS)) > 0 ) - { - fseek(PRICES[ind].fp,(height * PRICES_MAXDATAPOINTS + 2) * sizeof(int64_t),SEEK_SET); - if ( fwrite(&smoothed,1,sizeof(smoothed),PRICES[ind].fp) != sizeof(smoothed) ) - fprintf(stderr,"error fwrite smoothed for ht.%d ind.%d\n",height,ind); - else fflush(PRICES[ind].fp); - } else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind); - } else fprintf(stderr,"error fread ptr64 for ht.%d ind.%d\n",height,ind); - } - } else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind); - } - fprintf(stderr,"height.%d\n",height); - } else fprintf(stderr,"error reading rawprices for ht.%d\n",height); - } else fprintf(stderr,"height.%d <= width.%d\n",height,width); - pthread_mutex_unlock(&pricemutex); - } else fprintf(stderr,"null PRICES[0].fp\n"); - } else fprintf(stderr,"numprices mismatch, height.%d\n",height); -} - -int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks) -{ - FILE *fp; int32_t retval = PRICES_MAXDATAPOINTS; - pthread_mutex_lock(&pricemutex); - if ( ind < KOMODO_MAXPRICES && (fp= PRICES[ind].fp) != 0 ) - { - fseek(fp,height * PRICES_MAXDATAPOINTS * sizeof(int64_t),SEEK_SET); - if ( fread(buf64,sizeof(int64_t),numblocks*PRICES_MAXDATAPOINTS,fp) != numblocks*PRICES_MAXDATAPOINTS ) - retval = -1; - } - pthread_mutex_unlock(&pricemutex); - return(retval); -} +void komodo_pricesupdate(int32_t height,CBlock *pblock); + +int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); + +void komodo_createminerstransactions(); From 2ba6e97cf67fece81f8f155f300f9c7a53a518fe Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 31 May 2021 18:08:14 -0500 Subject: [PATCH 09/58] working on komodo_utils.h --- src/Makefile.am | 2 +- src/cc/CCcustom.cpp | 20 - src/komodo.cpp | 305 ++---- src/komodo.h | 142 +-- src/komodo_bitcoind.cpp | 396 ++++---- src/komodo_bitcoind.h | 155 ++- src/komodo_ccdata.cpp | 4 +- src/komodo_ccdata.h | 1 - src/komodo_curve25519.cpp | 23 +- src/komodo_curve25519.h | 18 +- src/komodo_cutils.h | 81 ++ src/komodo_events.cpp | 45 +- src/komodo_events.h | 44 +- src/komodo_gateway.cpp | 910 +++++++++--------- src/komodo_gateway.h | 188 ++-- src/komodo_globals.cpp | 186 ++++ src/komodo_globals.h | 171 +--- src/komodo_interest.cpp | 137 +++ src/komodo_interest.h | 180 +--- src/komodo_jumblr.cpp | 756 +++++++++++++++ src/komodo_jumblr.h | 788 ++-------------- src/komodo_kv.cpp | 197 ++++ src/komodo_kv.h | 186 +--- src/komodo_notary.cpp | 1297 ++++++++++++++++++++++++++ src/komodo_notary.h | 487 +--------- src/komodo_pax.cpp | 596 ++++++++++++ src/komodo_pax.h | 611 +----------- src/komodo_utils.cpp | 1864 +++++++++++++++++++++++++++++++++++++ src/komodo_utils.h | 73 +- src/mini-gmp.h | 10 + src/wallet/rpcwallet.cpp | 1 - 31 files changed, 6136 insertions(+), 3738 deletions(-) create mode 100644 src/komodo_cutils.h create mode 100644 src/komodo_globals.cpp create mode 100644 src/komodo_interest.cpp create mode 100644 src/komodo_jumblr.cpp create mode 100644 src/komodo_kv.cpp create mode 100644 src/komodo_notary.cpp create mode 100644 src/komodo_pax.cpp create mode 100644 src/komodo_utils.cpp diff --git a/src/Makefile.am b/src/Makefile.am index cb8ee654d5a..c2903fbc77b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,7 +53,7 @@ LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a -LIBCJSON-libcjson.a +LIBCJSON=libcjson.a if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 6c66b3599fd..b5f949cefd7 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -27,7 +27,6 @@ #include "CCOracles.h" #include "CCPrices.h" #include "CCPegs.h" -#include "CCMarmara.h" #include "CCPayments.h" #include "CCGateways.h" #include "CCtokens.h" @@ -189,17 +188,6 @@ uint8_t PegsCCpriv[32] = { 0x52, 0x56, 0x4c, 0x78, 0x87, 0xf7, 0xa2, 0x39, 0xb0, #undef FUNCNAME #undef EVALCODE -// Marmara -#define FUNCNAME IsMarmaraInput -#define EVALCODE EVAL_MARMARA -const char *MarmaraCCaddr = "RGLSRDnUqTB43bYtRtNVgmwSSd1sun2te8"; -const char *MarmaraNormaladdr = "RMN25Tn8NNzcyQDiQNuMp8UmwLMFd9thYc"; -char MarmaraCChexstr[67] = { "03afc5be570d0ff419425cfcc580cc762ab82baad88c148f5b028d7db7bfeee61d" }; -uint8_t MarmaraCCpriv[32] = { 0x7c, 0x0b, 0x54, 0x9b, 0x65, 0xd4, 0x89, 0x57, 0xdf, 0x05, 0xfe, 0xa2, 0x62, 0x41, 0xa9, 0x09, 0x0f, 0x2a, 0x6b, 0x11, 0x2c, 0xbe, 0xbd, 0x06, 0x31, 0x8d, 0xc0, 0xb9, 0x96, 0x76, 0x3f, 0x24 }; -#include "CCcustom.inc" -#undef FUNCNAME -#undef EVALCODE - // Payments #define FUNCNAME IsPaymentsInput #define EVALCODE EVAL_PAYMENTS @@ -402,14 +390,6 @@ struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode) cp->validate = PegsValidate; cp->ismyvin = IsPegsInput; break; - case EVAL_MARMARA: - strcpy(cp->unspendableCCaddr,MarmaraCCaddr); - strcpy(cp->normaladdr,MarmaraNormaladdr); - strcpy(cp->CChexstr,MarmaraCChexstr); - memcpy(cp->CCpriv,MarmaraCCpriv,32); - cp->validate = MarmaraValidate; - cp->ismyvin = IsMarmaraInput; - break; case EVAL_PAYMENTS: strcpy(cp->unspendableCCaddr,PaymentsCCaddr); strcpy(cp->normaladdr,PaymentsNormaladdr); diff --git a/src/komodo.cpp b/src/komodo.cpp index cf18b0e9489..b3be0da823d 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2014-2021 The SuperNET Developers and others. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -12,16 +12,8 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ -#include "komodo_globals.h" - #include "komodo.h" -int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); // defined in rawtransaction.cpp -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); // defined in komodo_events.h - -/** - * @param height the new height of the chain - */ void komodo_currentheight_set(int32_t height) { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -30,10 +22,6 @@ void komodo_currentheight_set(int32_t height) } extern struct NSPV_inforesp NSPV_inforesult; - -/**** - * @returns the current height of the chain - */ int32_t komodo_currentheight() { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -46,15 +34,6 @@ int32_t komodo_currentheight() else return(0); } -/*** - * Parse 1 record from the state file - * NOTE: This is a (slower?) alternative to komodo_faststateinit - * @param sp the state - * @param fp the file - * @param symbol the symbol - * @param dest a buffer - * @returns the record type processed or -1 on error - */ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest) { static int32_t errs; @@ -190,15 +169,6 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char } else return(-1); } -/**** - * Read a section of memory - * @param dest the destination - * @param size the size to read - * @param filedata the memory - * @param fposp the position to read from - * @param datalen the size of filedata - * @returns the number of bytes read or -1 on error - */ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen) { if ( *fposp+size <= datalen ) @@ -210,84 +180,41 @@ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datal return(-1); } - -/**** - * Parse file to get komodo events - * @param sp the state (stores the events) - * @param filedata the data to parse - * @param fposp the file position - * @param datalen the length of filedata - * @param symbol the currency symbol - * @param dest - * @returns the record type parsed, or number of errors if negative - */ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) { - int32_t errs = 1; // number of errors found - uint8_t rec_type = 0; // type of record found - int32_t ht; // height - bool symbol_matches = false; - long fpos = *fposp; // current position in data stream - + static int32_t errs; + int32_t func= -1,ht,notarized_height,MoMdepth,num,matched=0; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; long fpos = *fposp; if ( fpos < datalen ) { - rec_type = filedata[fpos++]; + func = filedata[fpos++]; if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - symbol_matches = true; - else - symbol_matches = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) // get height + matched = 1; + else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) errs++; - if ( rec_type == 'P' ) // pubkey record + if ( func == 'P' ) { - // while we're doing both old and new way - long temp_pos = fpos; - // old way - int32_t num; - if ( (num = filedata[fpos++]) <= 64 ) // number of keys in this record + if ( (num= filedata[fpos++]) <= 64 ) { - uint8_t pubkeys[64][33]; if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) errs++; else { //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) + if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); } - } - else - printf("illegal number of keys.%d\n",num); - fpos = temp_pos; - // new way - try - { - std::shared_ptr pubkey = std::make_shared(filedata, fpos, datalen, ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && symbol_matches) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - sp->add_event(symbol, ht, pubkey); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } + } else printf("illegal num.%d\n",num); } - else if ( rec_type == 'N' || rec_type == 'M' ) // notary event + else if ( func == 'N' || func == 'M' ) { - // old way - long temp_pos = fpos; - int32_t notarized_height; if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) errs++; - uint256 notarized_hash; if ( memread(¬arized_hash,sizeof(notarized_hash),filedata,&fpos,datalen) != sizeof(notarized_hash) ) errs++; - uint256 notarized_desttxid; if ( memread(¬arized_desttxid,sizeof(notarized_desttxid),filedata,&fpos,datalen) != sizeof(notarized_desttxid) ) errs++; - int32_t MoMdepth; - uint256 MoM; - if ( rec_type == 'M' ) + if ( func == 'M' ) { if ( memread(&MoM,sizeof(MoM),filedata,&fpos,datalen) != sizeof(MoM) ) errs++; @@ -302,20 +229,8 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long MoMdepth = 0; } komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); - fpos = temp_pos; // reset for new way - // new way - try - { - std::shared_ptr notarized = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'M'); - sp->add_event(symbol, ht, notarized); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } } - else if ( rec_type == 'U' ) // deprecated + else if ( func == 'U' ) // deprecated { uint8_t n,nid; uint256 hash; uint64_t mask; n = filedata[fpos++]; @@ -326,56 +241,26 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long if ( memread(&hash,sizeof(hash),filedata,&fpos,datalen) != sizeof(hash) ) errs++; } - else if ( rec_type == 'K' ) // kmd event + else if ( func == 'K' ) { - long temp_pos = fpos; - // old way int32_t kheight; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); - fpos = temp_pos; // reset for new way - // new way - try - { - std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht); - sp->add_event(symbol, ht, kmd_height); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } + komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); } - else if ( rec_type == 'T' ) // kmd event with timestamp + else if ( func == 'T' ) { - long temp_pos = fpos; - // old way int32_t kheight,ktimestamp; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; if ( memread(&ktimestamp,sizeof(ktimestamp),filedata,&fpos,datalen) != sizeof(ktimestamp) ) errs++; - //if ( symbol_matches != 0 ) global independent states -> inside *sp + //if ( matched != 0 ) global independent states -> inside *sp //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); - fpos = temp_pos; - // new way - try - { - std::shared_ptr kmd_height = std::make_shared(filedata, fpos, datalen, ht, rec_type == 'T'); - sp->add_event(symbol, ht, kmd_height); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } } - else if ( rec_type == 'R' ) // opreturn + else if ( func == 'R' ) { - long temp_pos = fpos; - // old way uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) errs++; @@ -389,7 +274,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long { if ( memread(opret,olen,filedata,&fpos,datalen) != olen ) errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && symbol_matches ) + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) { int32_t i; for (i=0; i opret = std::make_shared(filedata, fpos, datalen, ht); - sp->add_event(symbol, ht, opret); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } } - else if ( rec_type == 'D' ) + else if ( func == 'D' ) { printf("unexpected function D[%d]\n",ht); } - else if ( rec_type == 'V' ) // pricefeed + else if ( func == 'V' ) { - long temp_pos = fpos; - // old way int32_t numpvals; uint32_t pvals[128]; numpvals = filedata[fpos++]; if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && memread(pvals,(int32_t)(sizeof(uint32_t)*numpvals),filedata,&fpos,datalen) == numpvals*sizeof(uint32_t) ) { - //if ( symbol_matches != 0 ) global shared state -> global PVALS + //if ( matched != 0 ) global shared state -> global PVALS //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); } else printf("error loading pvals[%d]\n",numpvals); - fpos = temp_pos; - // new way - try - { - std::shared_ptr feed = std::make_shared(filedata, fpos, datalen, ht); - sp->add_event(symbol, ht, feed); - } - catch(const komodo::parse_error& pe) - { - printf("%s\n", pe.what()); - errs++; - } } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); *fposp = fpos; - return(rec_type); + return(func); } - return -errs; + return(-1); } -/**** - * Update state, including persisting to disk - * @param height - * @param notarpubs - * @param numnotaries - * @param notaryid - * @param txhash - * @param voutmask - * @param numvouts - * @param pvals - * @param numpvals - * @param KMDheight - * @param KMDtimestamp - * @param opretvalue - * @param opretbuf - * @param opretlen - * @param vout - * @param MoM - * @param MoMdepth - */ -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts, - uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) { - static FILE *fp; - static int32_t errs; - static int32_t didinit; - static uint256 zero; - struct komodo_state *sp; - char fname[512]; - char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - char dest[KOMODO_ASSETCHAIN_MAXLEN]; - int32_t retval; - int32_t ht; - int32_t func; - uint8_t num; - uint8_t pubkeys[64][33]; + static FILE *fp; static int32_t errs,didinit; static uint256 zero; + struct komodo_state *sp; char fname[512],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t retval,ht,func; uint8_t num,pubkeys[64][33]; if ( didinit == 0 ) { portable_mutex_init(&KOMODO_KV_mutex); portable_mutex_init(&KOMODO_CC_mutex); didinit = 1; } - // Get the correct state object if ( (sp= komodo_stateptr(symbol,dest)) == 0 ) { KOMODO_INITDONE = (uint32_t)time(NULL); printf("[%s] no komodo_stateptr\n",ASSETCHAINS_SYMBOL); return; } + //printf("[%s] (%s) -> (%s)\n",ASSETCHAINS_SYMBOL,symbol,dest); if ( fp == 0 ) { - // get the state filename and open it komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); if ( (fp= fopen(fname,"rb+")) != 0 ) { - if ( (retval= komodo_faststateinit(sp,fname,symbol,dest)) > 0 ) // try a fast state init + if ( (retval= komodo_faststateinit(sp,fname,symbol,dest)) > 0 ) fseek(fp,0,SEEK_END); else { - // fast state init failed. Do it the long way. + fprintf(stderr,"komodo_faststateinit retval.%d\n",retval); while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 ) ; } @@ -520,10 +346,12 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar } if ( height <= 0 ) { + //printf("early return: stateupdate height.%d\n",height); return; } if ( fp != 0 ) // write out funcid, height, other fields, call side effect function { + //printf("fpos.%ld ",ftell(fp)); if ( KMDheight != 0 ) { if ( KMDtimestamp != 0 ) @@ -562,6 +390,8 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar errs++; if ( fwrite(opretbuf,1,olen,fp) != olen ) errs++; +//printf("create ht.%d R opret[%d] sp.%p\n",height,olen,sp); + //komodo_opreturn(height,opretvalue,opretbuf,olen,txhash,vout); komodo_eventadd_opreturn(sp,symbol,height,txhash,opretvalue,vout,opretbuf,olen); } else if ( notarypubs != 0 && numnotaries > 0 ) @@ -577,6 +407,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar } else if ( voutmask != 0 && numvouts > 0 ) { + //printf("ht.%d func U %d %d errs.%d hashsize.%ld\n",height,numvouts,notaryid,errs,sizeof(txhash)); fputc('U',fp); if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) errs++; @@ -586,6 +417,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar errs++; if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) errs++; + //komodo_eventadd_utxo(sp,symbol,height,notaryid,txhash,voutmask,numvouts); } else if ( pvals != 0 && numpvals > 0 ) { @@ -602,10 +434,13 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals ) errs++; komodo_eventadd_pricefeed(sp,symbol,height,pvals,numpvals); + //printf("ht.%d V numpvals[%d]\n",height,numpvals); } + //printf("save pvals height.%d numpvals.%d\n",height,numpvals); } else if ( height != 0 ) { + //printf("ht.%d func N ht.%d errs.%d\n",height,NOTARIZED_HEIGHT,errs); if ( sp != 0 ) { if ( sp->MoMdepth != 0 && sp->MoM != zero ) @@ -633,12 +468,6 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar } } -/***** - * Validate the chain - * @param srchash - * @param notarized_height - * @returns 0 on failure, 1 on success - */ int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) { static int32_t last_rewind; int32_t rewindtarget; CBlockIndex *pindex; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; @@ -664,28 +493,7 @@ int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height) } else return(1); } -/**** - * Update vout - * @param fJustCheck - * @param isratificationp - * @param notaryid - * @param scriptbuf - * @param scriptlen - * @param height - * @param txhash - * @param i - * @param j - * @param voutmaskp - * @param specialtxp - * @param notarizedheightp - * @param value - * @param notarized - * @param signedmask - * @param timestamp - * @returns negative number on error, notaryid on success - */ -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) +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) { static uint256 zero; static FILE *signedfp; int32_t opretlen,nid,offset,k,MoMdepth,matched,len = 0; uint256 MoM,srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; @@ -938,15 +746,8 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed // OP_RETURN: 'D' -> deposit, 'W' -> withdraw -/**** - * Compare notaries - * @param scirptPubKey - * @param scriptlen - * @param pubkeys - * @param numnotaries - * @param rmd160 - * @returns -1 on failure, 0 or positive number on success - */ +int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); + int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]) { int32_t i; @@ -961,18 +762,12 @@ int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys return(-1); } -/**** - * @param fJustCheck - * @param pindex - * @param block - * @returns positive number on success, -1 or 0 on error - */ +// int32_t (!!!) +/* + read blackjok3rtt comments in main.cpp +*/ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) { - // returns int32_t (!!!) - /* - read blackjok3rtt comments in main.cpp - */ static int32_t hwmheight; int32_t staked_era; static int32_t lastStakedEra; std::vector notarisations; @@ -1096,6 +891,8 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) sp->NOTARIZED_HASH = block.GetHash(); sp->NOTARIZED_DESTTXID = txhash; } + //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + // printf("(tx.%d: ",i); for (j=0; j= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) @@ -1131,6 +930,8 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) } } } + //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + // printf(") "); if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d notarized.%d special.%d isratification.%d\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts,notarized,specialtx,isratification); if ( !fJustCheck && (notarized != 0 && (notarizedheight != 0 || specialtx != 0)) ) diff --git a/src/komodo.h b/src/komodo.h index 3e0a99ac1db..5094b16e48b 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -13,14 +13,12 @@ * * ******************************************************************************/ #pragma once +#include +#include +#include +#include -#include "komodo_defs.h" #include "uint256.h" -#include "notaries_staked.h" - -#ifdef _WIN32 -#define printf(...) -#endif // Todo: // verify: reorgs @@ -28,135 +26,50 @@ #define KOMODO_ASSETCHAINS_WAITNOTARIZE #define KOMODO_PAXMAX (10000 * COIN) extern int32_t NOTARIZED_HEIGHT; +uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; -#include -#include -#include -#include #include "uthash.h" #include "utlist.h" +#include "chain.h" + +int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n); +void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); +int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); +bool check_pprevnotarizedht(); #include "komodo_structs.h" +#include "komodo_globals.h" #include "komodo_utils.h" #include "komodo_curve25519.h" -#include "komodo_cJSON.h" +#include "komodo_cJSON.c" #include "komodo_bitcoind.h" #include "komodo_interest.h" #include "komodo_pax.h" #include "komodo_notary.h" +int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); #include "komodo_kv.h" #include "komodo_jumblr.h" #include "komodo_gateway.h" #include "komodo_events.h" #include "komodo_ccdata.h" -/** - * @param height the new height of the chain - */ void komodo_currentheight_set(int32_t height); -/**** - * @returns the current height of the chain - */ int32_t komodo_currentheight(); -/*** - * Parse 1 record from the state file - * NOTE: This is a (slower?) alternative to komodo_faststateinit - * @param sp the state - * @param fp the file - * @param symbol the symbol - * @param dest a buffer - * @returns the record type processed or -1 on error - */ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); -/**** - * Read a section of memory - * @param dest the destination - * @param size the size to read - * @param filedata the memory - * @param fposp the position to read from - * @param datalen the size of filedata - * @returns the number of bytes read or -1 on error - */ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen); -/**** - * Parse file to get komodo events - * @param sp the state (stores the events) - * @param filedata the data to parse - * @param fposp the file position - * @param datalen the length of filedata - * @param symbol the currency symbol - * @param dest - * @returns the record type parsed, or number of errors if negative - */ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); -/**** - * Update state, including persisting to disk - * @param height - * @param notarpubs - * @param numnotaries - * @param notaryid - * @param txhash - * @param voutmask - * @param numvouts - * @param pvals - * @param numpvals - * @param KMDheight - * @param KMDtimestamp - * @param opretvalue - * @param opretbuf - * @param opretlen - * @param vout - * @param MoM - * @param MoMdepth - */ -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts, - uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t - opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); - -/***** - * Validate the chain - * @param srchash - * @param notarized_height - * @returns 0 on failure, 1 on success - */ +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); + int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height); -/**** - * Update vout - * @param fJustCheck - * @param isratificationp - * @param notaryid - * @param scriptbuf - * @param scriptlen - * @param height - * @param txhash - * @param i - * @param j - * @param voutmaskp - * @param specialtxp - * @param notarizedheightp - * @param value - * @param notarized - * @param signedmask - * @param timestamp - * @returns negative number on error, notaryid on success - */ -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); - -/*int32_t komodo_isratify(int32_t isspecial,int32_t numvalid) -{ - if ( isspecial != 0 && numvalid >= KOMODO_MINRATIFY ) - return(1); - else return(0); -}*/ +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); // Special tx have vout[0] -> CRYPTO777 // with more than KOMODO_MINRATIFY pay2pubkey outputs -> ratify @@ -164,21 +77,12 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar // if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed // OP_RETURN: 'D' -> deposit, 'W' -> withdraw -/**** - * Compare notaries - * @param scirptPubKey - * @param scriptlen - * @param pubkeys - * @param numnotaries - * @param rmd160 - * @returns -1 on failure, 0 or positive number on success - */ +int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n); + int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys[64][33],int32_t numnotaries,uint8_t rmd160[20]); -/**** - * @param fJustCheck - * @param pindex - * @param block - * @returns positive number on success, -1 or 0 on error - */ +// int32_t (!!!) +/* + read blackjok3rtt comments in main.cpp +*/ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block); diff --git a/src/komodo_bitcoind.cpp b/src/komodo_bitcoind.cpp index 274181aef89..1baa1f7b50c 100644 --- a/src/komodo_bitcoind.cpp +++ b/src/komodo_bitcoind.cpp @@ -12,36 +12,8 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -// komodo functions that interact with bitcoind C++ -#include "komodo_notary.h" // for komodo_init() -#include "komodo_globals.h" // for KMD_PORT, BTCUSERPASS - #include "komodo_bitcoind.h" -const char *LOG_KOMODOBITCOIND = "komodostaking"; - -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); // defined in komodo_notary.h -int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); // defined in komodo_notary.h -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); // declared in komodo.h -unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); // declared in pow.h -bool EnsureWalletIsAvailable(bool avoidException); // declared in rpcwallet.h -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); // defined in komodo_interest.h -CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); // defined in main.h - -extern bool fRequestShutdown; -extern CScript KOMODO_EARLYTXID_SCRIPTPUB; - -uint32_t komodo_heightstamp(int32_t height); - -// 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) - - /************************************************************************ * * Initialize the string handler so that it is thread safe @@ -79,20 +51,6 @@ int tx_height( const uint256 &hash ){ return nHeight; } -// hash value to string for logging -static std::string hash2str(arith_uint256 hashval, int nbits) -{ - std::ostringstream os; - - if (nbits < 8) - nbits = 8; - if (nbits > 32) - nbits = 32; - - for (int32_t i = 31; i >= (31 - nbits + 1); i--) - os << std::setw(2) << std::hex << std::setfill('0') << (int)((uint8_t *)&hashval)[i]; - return os.str(); -} /************************************************************************ * @@ -115,8 +73,6 @@ size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string * return(size * nmemb); } - - /************************************************************************ * * return the current system time in milliseconds @@ -389,8 +345,11 @@ char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port) { sprintf(url,(char *)"http://127.0.0.1:%u",port); sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); + // printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,KMDUSERPASS); retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); + //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); } + // fprintf(stderr, "RPC RESP: %s\n", retstr2); return(retstr2); } @@ -416,6 +375,7 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heig { if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getinfo",params,port)) != 0 ) { + //printf("(%s)\n",jsonstr); if ( (json= cJSON_Parse(jsonstr)) != 0 ) { if ( (item= jobj(json,(char *)"result")) != 0 ) @@ -430,6 +390,7 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heig } else { if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getblockchaininfo",params,port)) != 0 ) { + //printf("(%s)\n",jsonstr); if ( (json= cJSON_Parse(jsonstr)) != 0 ) { if ( (item= jobj(json,(char *)"result")) != 0 ) @@ -445,6 +406,7 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heig sprintf(params,"[\"%s\", 1]",txidstr); if ( (jsonstr= komodo_issuemethod(userpass,(char *)"getrawtransaction",params,port)) != 0 ) { + //printf("(%s)\n",jsonstr); if ( (json= cJSON_Parse(jsonstr)) != 0 ) { if ( (item= jobj(json,(char *)"result")) != 0 ) @@ -453,6 +415,7 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heig if ( txid_confirmations > 0 && height > txid_confirmations ) txid_height = height - txid_confirmations; else txid_height = height; + //printf("height.%d tconfs.%d txid_height.%d\n",height,txid_confirmations,txid_height); } free_json(json); } @@ -462,16 +425,15 @@ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heig return(txid_height); } - -int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 notarized_hash) +int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH) { int32_t i; uint256 hash; char params[256]; for (i=0; i<32; i++) ((uint8_t *)&hash)[i] = script[2+i]; - if ( hash == notarized_hash ) + if ( hash == NOTARIZED_HASH ) return(1); for (i=0; i<32; i++) - printf("%02x",((uint8_t *)¬arized_hash)[i]); + printf("%02x",((uint8_t *)&NOTARIZED_HASH)[i]); printf(" notarized, "); for (i=0; i<32; i++) printf("%02x",((uint8_t *)&hash)[i]); @@ -485,15 +447,22 @@ void komodo_reconsiderblock(uint256 blockhash) sprintf(params,"[\"%s\"]",blockhash.ToString().c_str()); if ( (jsonstr= komodo_issuemethod(ASSETCHAINS_USERPASS,(char *)"reconsiderblock",params,ASSETCHAINS_RPCPORT)) != 0 ) { + //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> (%s)\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT,jsonstr); free(jsonstr); } + //fprintf(stderr,"komodo_reconsiderblock.(%s) (%s %u) -> NULL\n",params,ASSETCHAINS_USERPASS,ASSETCHAINS_RPCPORT); } -int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 notarized_hash,uint256 notarized_desttxid) +int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID) { char params[256],*jsonstr,*hexstr; uint8_t *script,_script[8192]; int32_t n,len,retval = -1; cJSON *json,*txjson,*vouts,*vout,*skey; script = _script; - sprintf(params,"[\"%s\", 1]",notarized_desttxid.ToString().c_str()); + /*params[0] = '['; + params[1] = '"'; + for (i=0; i<32; i++) + sprintf(¶ms[i*2 + 2],"%02x",((uint8_t *)&NOTARIZED_DESTTXID)[31-i]); + strcat(params,"\", 1]");*/ + sprintf(params,"[\"%s\", 1]",NOTARIZED_DESTTXID.ToString().c_str()); if ( strcmp(symbol,ASSETCHAINS_SYMBOL[0]==0?(char *)"KMD":ASSETCHAINS_SYMBOL) != 0 ) return(0); if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) @@ -505,8 +474,9 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t if ( ASSETCHAINS_SYMBOL[0] != 0 ) { jsonstr = komodo_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,KMD_PORT); + //printf("userpass.(%s) got (%s)\n",KMDUSERPASS,jsonstr); } - } + }//else jsonstr = _dex_getrawtransaction(); else return(0); // need universal way to issue DEX* API, since notaries mine most blocks, this ok } else if ( strcmp(dest,"BTC") == 0 ) @@ -515,6 +485,7 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t { jsonstr = komodo_issuemethod(BTCUSERPASS,(char *)"getrawtransaction",params,DEST_PORT); } + //else jsonstr = _dex_getrawtransaction(); else return(0); } else @@ -535,7 +506,7 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t { if ( (hexstr= jstr(skey,(char *)"hex")) != 0 ) { - //printf("HEX.(%s) vs hash.%s\n",hexstr,notarized_hash.ToString().c_str()); + //printf("HEX.(%s) vs hash.%s\n",hexstr,NOTARIZED_HASH.ToString().c_str()); len = strlen(hexstr) >> 1; decode_hex(script,len,hexstr); if ( script[1] == 0x4c ) @@ -548,7 +519,7 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t script += 2; len -= 2; } - retval = komodo_verifynotarizedscript(height,script,len,notarized_hash); + retval = komodo_verifynotarizedscript(height,script,len,NOTARIZED_HASH); } } } @@ -571,36 +542,85 @@ CScript komodo_makeopret(CBlock *pblock, bool fNew) return(opret); } +/*uint256 komodo_getblockhash(int32_t height) + { + uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32]; + memset(&hash,0,sizeof(hash)); + sprintf(params,"[%d]",height); + if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_RPCPORT)) != 0 ) + { + if ( (result= cJSON_Parse(jsonstr)) != 0 ) + { + if ( (hexstr= jstr(result,(char *)"result")) != 0 ) + { + if ( is_hexstr(hexstr,0) == 64 ) + { + decode_hex(revbuf,32,hexstr); + for (i=0; i<32; i++) + ((uint8_t *)&hash)[i] = revbuf[31-i]; + } + } + free_json(result); + } + printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash); + free(jsonstr); + } + return(hash); + } + + uint256 _komodo_getblockhash(int32_t height);*/ + uint64_t komodo_seed(int32_t height) { - uint64_t seed = (height << 13) ^ (height << 2); - seed <<= 21; - seed |= (height & 0xffffffff); - seed ^= (seed << 17) ^ (seed << 1); - return seed; + uint64_t seed = 0; + /*if ( 0 ) // problem during init time, seeds are needed for loading blockindex, so null seeds... + { + uint256 hash,zero; CBlockIndex *pindex; + memset(&hash,0,sizeof(hash)); + memset(&zero,0,sizeof(zero)); + if ( height > 10 ) + height -= 10; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + hash = _komodo_getblockhash(height); + if ( memcmp(&hash,&zero,sizeof(hash)) == 0 ) + hash = komodo_getblockhash(height); + int32_t i; + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&hash)[i]); + printf(" seed.%d\n",height); + seed = arith_uint256(hash.GetHex()).GetLow64(); + } + else*/ + { + seed = (height << 13) ^ (height << 2); + seed <<= 21; + seed |= (height & 0xffffffff); + seed ^= (seed << 17) ^ (seed << 1); + } + return(seed); } -// get previous staking utxo opret, address and txtime uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr) { CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts; *valuep = 0; - if (!GetTransaction(hash, tx, hashBlock, true)) + if (!GetTransaction(hash, tx, +#ifndef KOMODO_ZCASH + Params().GetConsensus(), +#endif + hashBlock, true)) { + //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); return(0); } numvouts = tx.vout.size(); - - if (n < numvouts) + //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); + if ( n < numvouts ) { *valuep = tx.vout[n].nValue; - opret = tx.vout[numvouts-1].scriptPubKey; - + opret = tx.vout[numvouts-1].scriptPubKey; if (ExtractDestination(tx.vout[n].scriptPubKey, address)) - { - strcpy(destaddr, CBitcoinAddress(address).ToString().c_str()); - LogPrint(LOG_KOMODOBITCOIND, "%s in stake tx found opret and destaddr=%s\n", __func__, destaddr); - } + strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); } return(tx.nLockTime); } @@ -611,24 +631,17 @@ CBlockIndex *komodo_getblockindex(uint256 hash) return((it != mapBlockIndex.end()) ? it->second : NULL); } -// Extension point to add preferences for stakes (dimxy) -// TODO: what if for some chain several chain's params require different multipliers. Which to select, max? -static int32_t GetStakeMultiplier(CTransaction &tx, int32_t nvout) -{ - int32_t multiplier = 1; // default value - - CAmount nValue = (nvout >= 0 && nvout < tx.vout.size() ? tx.vout[nvout].nValue : -1); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "stake multiplier=" << multiplier << " nValue=" << nValue << std::endl); - return multiplier; -} - 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, hashBlock, true)) + if (!GetTransaction(hash, tx, +#ifndef KOMODO_ZCASH + Params().GetConsensus(), +#endif + hashBlock, true)) { - fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); // TODO: comment + //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 ) @@ -637,9 +650,7 @@ uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr) //fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); if ( n < tx.vout.size() ) { - int32_t stakemultiplier = GetStakeMultiplier(tx, n); - *valuep = tx.vout[n].nValue * stakemultiplier; - + *valuep = tx.vout[n].nValue; if (ExtractDestination(tx.vout[n].scriptPubKey, address)) strcpy(destaddr,CBitcoinAddress(address).ToString().c_str()); } @@ -674,7 +685,7 @@ int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp) int32_t komodo_hasOpRet(int32_t height, uint32_t timestamp) { - return((komodo_newStakerActive(height, timestamp) == 1)); + return((ASSETCHAINS_MARMARA!=0 || komodo_newStakerActive(height, timestamp) == 1)); } bool komodo_checkopret(CBlock *pblock, CScript &merkleroot) @@ -688,6 +699,8 @@ bool komodo_hardfork_active(uint32_t time) return ( (ASSETCHAINS_SYMBOL[0] == 0 && chainActive.Height() > nDecemberHardforkHeight) || (ASSETCHAINS_SYMBOL[0] != 0 && time > nStakedDecemberHardforkTimestamp) ); //December 2019 hardfork } +bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx); + uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey) { std::vector vLeaves; @@ -710,59 +723,53 @@ uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHe return GetMerkleRoot(vLeaves); } - -// checks if block is PoS: -// last tx should point to the previous staking utxo (that is spent to self) -// returns 1 if this is PoS block and 0 if false int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout) { - int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid, merkleroot; CScript prevTxOpret; + int32_t n,vout,numvouts,ret; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid, merkleroot; CScript opret; if ( ASSETCHAINS_STAKED != 0 ) { n = pblock->vtx.size(); - - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht." << height << " check for PoS numtx." << n << " numvins." << pblock->vtx[n-1].vin.size() << " numvouts." << pblock->vtx[n-1].vout.size() << std::endl); + //fprintf(stderr,"ht.%d check for PoS numtx.%d numvins.%d numvouts.%d\n",height,n,(int32_t)pblock->vtx[n-1].vin.size(),(int32_t)pblock->vtx[n-1].vout.size()); if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) { - // get previous tx and check if it was spent to self - txid = pblock->vtx[n-1].vin[0].prevout.hash; + txid = pblock->vtx[n-1].vin[0].prevout.hash; vout = pblock->vtx[n-1].vin[0].prevout.n; - txtime = komodo_txtime(prevTxOpret, &value, txid, vout, destaddr); // get previous stake tx opret and addr - if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) // get current tx vout address + txtime = komodo_txtime(opret,&value,txid,vout,destaddr); + if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) { if ( addressout != 0 ) *addressout = voutaddress; strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str()); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "check voutaddr." << voutaddr << " vs prevtx destaddr." << destaddr << std::endl); - if ( komodo_newStakerActive(height, pblock->nTime) != 0 ) + //fprintf(stderr,"voutaddr.%s vs destaddr.%s\n",voutaddr,destaddr); + if ( komodo_newStakerActive(height, pblock->nTime) != 0 ) { if ( DecodeStakingOpRet(pblock->vtx[n-1].vout[1].scriptPubKey, merkleroot) != 0 && komodo_calcmerkleroot(pblock, pblock->hashPrevBlock, height, false, pblock->vtx[0].vout[0].scriptPubKey) == merkleroot ) { return(1); } - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "ht=" << height << " incorrect stake tx (komodo_calcmerkleroot failed)" << std::endl); } else { if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 ) { - return(1); - } - else - { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " incorrect stake tx (value or destaddr not matched)" << std::endl); + if ( ASSETCHAINS_MARMARA == 0 ) + return(1); + else + { + if ( pblock->vtx[n-1].vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= pblock->vtx[n-1].vout.size()) == 2 ) + { + //fprintf(stderr,"validate proper %s %s signature and unlockht preservation\n",voutaddr,destaddr); + return(MarmaraPoScheck(destaddr,opret,pblock->vtx[n-1])); + } + else + { + fprintf(stderr,"reject ht.%d PoS block\n",height); + return(strcmp(ASSETCHAINS_SYMBOL,"MTST2") == 0); // allow until MTST3 + } + } } } } - else - { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " not a stake tx (couldn't ExtractDestination)" << std::endl); - } - } - else - { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " not a stake tx (n, vin.size or vout.size not matched)" << std::endl); } - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "ht=" << height << " return=0" << std::endl); } return(0); } @@ -847,7 +854,7 @@ int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) if ( block->vtx[0].vout.size() > 0 ) { txnouttype whichType; - std::vector> vch = std::vector>(); + vector> vch = vector>(); if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY) { CPubKey pubKey(vch[0]); @@ -1380,13 +1387,10 @@ uint32_t komodo_segid32(char *coinaddr) int8_t komodo_segid(int32_t nocache,int32_t height) { CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout,newStakerActive; uint256 txid,merkleroot; CScript opret; int8_t segid = -1; - if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 ) { - if (nocache == 0 && pindex->segid >= -1) { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "return cached segid, height." << height << " -> " << (int)pindex->segid << std::endl); // uncommented + if ( nocache == 0 && pindex->segid >= -1 ) return(pindex->segid); - } if ( komodo_blockload(block,pindex) == 0 ) { newStakerActive = komodo_newStakerActive(height, block.nTime); @@ -1405,7 +1409,6 @@ int8_t komodo_segid(int32_t nocache,int32_t height) { segid = komodo_segid32(voutaddr) & 0x3f; //fprintf(stderr, "komodo_segid: ht.%i --> %i\n",height,pindex->segid); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "set calculated segid, height." << height << " -> " << (int)pindex->segid << std::endl); // uncommented } } //else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height); } @@ -1415,13 +1418,6 @@ int8_t komodo_segid(int32_t nocache,int32_t height) if ( pindex->segid == -2 ) pindex->segid = segid; } - - else - { - // fprintf(stderr, "%s pindex==null ht.%d default value=%d\n", __func__, height, segid); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "pindex==null ht." << height << " segid default value=" << (int)segid << std::endl); - } - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "ht." << height << " return segid=" << (int)segid << std::endl); return(segid); } @@ -1487,7 +1483,7 @@ arith_uint256 komodo_adaptivepow_target(int32_t height,arith_uint256 bnTarget,ui arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc,int32_t newStakerActive) { - int32_t oldflag = 0, dispflag = 0 /*set to 1 to debug segids*/; + int32_t oldflag = 0,dispflag = 0; CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val; *percPoSp = percPoS = 0; @@ -1504,8 +1500,6 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he } else easydiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow); - - std::ostringstream strSegids; // for logging segids flags for (i=n=m=0; i<100; i++) { ht = height - 100 + i; @@ -1517,22 +1511,20 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he { n++; percPoS++; - if (dispflag != 0 && ASSETCHAINS_STAKED < 100) - strSegids << "0"; // fprintf(stderr,"0"); - not to contaminate 00011100110 output with deeper printing + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"0"); } else { - if (dispflag != 0 && ASSETCHAINS_STAKED < 100) - strSegids << "1"; // fprintf(stderr,"1"); - not to contaminate 00011100110 output with deeper printing + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) + fprintf(stderr,"1"); sum += UintToArith256(pindex->GetBlockHash()); m++; } } //else fprintf(stderr, "pindex returned null ht.%i\n",ht); - if (dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9) - strSegids << " " << percPoS << " "; // fprintf(stderr," %d, ", percPoS); + if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9 ) + fprintf(stderr," %d, ",percPoS); } - if (dispflag != 0 && ASSETCHAINS_STAKED < 100) - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << strSegids.str() << std::endl); if ( m+n < 100 ) { // We do actual PoS % at the start. Requires coin distribution in first 10 blocks! @@ -1542,8 +1534,7 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100; } if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 ) - LogPrint(LOG_KOMODOBITCOIND," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); - + fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height); *percPoSp = percPoS; if ( m > 0 ) { @@ -1609,7 +1600,7 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he 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) { - 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,iter=0; int64_t diff=0; uint32_t txtime,segid32,winner = 0 ; uint64_t value,coinage; + 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 ) { @@ -1623,7 +1614,6 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 ) { //fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "null value=" << value << " txtime=" << txtime << " blocktime=" << blocktime << " prevtime=" << prevtime << std::endl); return(0); } if ( value < SATOSHIDEN ) @@ -1636,7 +1626,6 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh komodo_segids(hashbuf,nHeight-101,100); segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout); segid = ((nHeight + segid32) & 0x3f); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "segid=" << segid << " address=" << address << std::endl); for (iter=0; iter<600; iter++) { if ( blocktime+iter+segid*2 < txtime+minage ) @@ -1705,21 +1694,18 @@ uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeigh 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\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff); */ - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << "block not validated as PoS:" << " hashval=" << hash2str(hashval, 8) << " > bnTarget=" << hash2str(bnTarget, 8) << " iter=" << iter << " winner=" << winner << " segid=" << segid << " coinage=" << coinage << " blocktime-txtime=" << blocktime - txtime << " ht=" << nHeight << " blocktime=" << blocktime << " value=" << value << " diff=" << diff << std::endl); break; } } - //fprintf(stderr,"iterated until iter.%d winner.%d value=%lld segid=%d validateflag=%d\n",iter,winner, value, segid, validateflag); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG2, stream << "iterated until iter=" << iter << " winner=" << winner << " value=" << value << " segid=" << segid << " validateflag=" << validateflag << std::endl); - if ( false && validateflag != 0 ) + //fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner); + if ( 0 && validateflag != 0 ) { - /*for (int32_t i=31; i>=24; i--) + for (i=31; i>=24; i--) fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); fprintf(stderr," vs "); - for (int32_t 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); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << "hashval=" << hash2str(hashval, 8) << " vs bnTarget=" << hash2str(bnTarget, 8) << "segid=" << segid << " iter=" << iter << " winner=" << winner << " coinage=" << coinage << " blocktime-txtime=" << blocktime - txtime << " ht=" << nHeight << " blocktime=" << blocktime << " value=" << value << " diff=" << diff << std::endl); + 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); @@ -1745,8 +1731,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ return(komodo_isPoS(pblock,height,0)); } txn_count = pblock->vtx.size(); - - // crashes RICK? CCLogPrintF(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, "%s checkblock ht.%d block=%s n.%d vins.%d vouts.%d vout[0].%.8f\n", __func__, height, pblock->GetHash().GetHex().c_str(), 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*/); //uncommented + //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); if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1+komodo_hasOpRet(height,pblock->nTime) ) { it = mapBlockIndex.find(pblock->hashPrevBlock); @@ -1761,16 +1746,11 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ { // checks utxo is eligible to stake this block eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF,(char *)"",PoSperc); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << " eligible=" << eligible << " pblock->nTime=" << pblock->nTime << std::endl); - } - else - { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << " komodo_isPoS ht=" << height << " block=" << pblock->GetHash().GetHex() << " returned false" << std::endl); } if ( eligible == 0 || eligible > pblock->nTime ) { - if ( false && ASSETCHAINS_STAKED < 100 ) - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << " PoS failure ht." << height << " eligible." << eligible << " vs blocktime." << pblock->nTime << " lag." << (eligible - pblock->nTime) << " -> check to see if it is PoW block" << std::endl); + 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)); } else { @@ -1783,16 +1763,19 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ */ if ( ASSETCHAINS_STAKED < 100 && bhash < POWTarget ) { - CCLogPrintF(LOG_KOMODOBITCOIND, CCLOG_ERROR, "[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL, height, bhash.GetCompact(), POWTarget.GetCompact()); + fprintf(stderr,"[%s:%i] isPoS but meets PoW diff nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL, height, bhash.GetCompact(), POWTarget.GetCompact()); isPoS = 0; } } } } - fprintf(stderr,"%s slow.%d ht.%d isPoS.%d\n", __func__,slowflag,height,isPoS); //uncommented + //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); + // for now, we will ignore slowFlag in the interest of keeping success/fail simpler for security purposes bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) { @@ -1852,7 +1835,12 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) { fprintf(stderr,"ERROR: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); } - else if (!GetTransaction(txid, tx, blkHash, true)) + else +#ifndef KOMODO_ZCASH + if (!GetTransaction(txid, tx, Params().GetConsensus(), blkHash, true)) +#else + if (!GetTransaction(txid, tx, blkHash, true)) +#endif { fprintf(stderr,"ERROR: invalid PoS block %s - no source transaction\n",blkHash.ToString().c_str()); } @@ -2302,11 +2290,10 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; if ( !CheckEquihashSolution(pblock, Params()) ) { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "slowflag." << slowflag << " ht." << height << " CheckEquihashSolution failed" << std::endl); + fprintf(stderr,"komodo_checkPOW slowflag.%d ht.%d CheckEquihashSolution failed\n",slowflag,height); return(-1); } hash = pblock->GetHash(); - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_DEBUG1, stream << "checking block." << hash.GetHex() << " ht." << height << " bits." << pblock->nBits << std::endl); bnTarget.SetCompact(pblock->nBits,&fNegative,&fOverflow); bhash = UintToArith256(hash); possible = komodo_block2pubkey33(pubkey33,pblock); @@ -2314,7 +2301,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in { if ( slowflag != 0 ) { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_INFO, stream << "height." << height << " slowflag." << slowflag << " possible."<< possible << " (is bhash > bnTarget)=" << (bhash > bnTarget) << std::endl); + fprintf(stderr,"height.%d slowflag.%d possible.%d cmp.%d\n",height,slowflag,possible,bhash > bnTarget); return(0); } BlockMap::const_iterator it = mapBlockIndex.find(pblock->hashPrevBlock); @@ -2374,7 +2361,12 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED,newStakerActive); if ( bhash > bnTarget ) { - LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " bnhash=" << hash2str(bhash, 16) << " > bnTarget=" << hash2str(bnTarget, 16) << " ht." << height << " PoW diff violation PoSperc." << PoSperc << " vs goalperc." << (int)ASSETCHAINS_STAKED << std::endl); + for (i=31; i>=16; i--) + 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 @@ -2385,7 +2377,6 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in if ( pblock->vtx.size() > 1 && pblock->vtx[pblock->vtx.size()-1].vout.size() == 2 && DecodeStakingOpRet(pblock->vtx[pblock->vtx.size()-1].vout[1].scriptPubKey, merkleroot) != 0 ) { fprintf(stderr, "[%s:%d] staking tx in PoW block, nBits.%u < target.%u\n", ASSETCHAINS_SYMBOL,height,bhash.GetCompact(),bnTarget.GetCompact()); - LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " staking tx found in PoW block, nBits=" << bhash.GetCompact() << " < target=" << bnTarget.GetCompact() << std::endl); return(-1); } // set the pindex->segid as this is now fully validated to be a PoW block. @@ -2401,8 +2392,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in } else if ( is_PoSblock < 0 ) { - //fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",ASSETCHAINS_SYMBOL,height,is_PoSblock); - LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " unexpected negative is_PoSblock." << is_PoSblock << std::endl); + fprintf(stderr,"[%s:%d] unexpected negative is_PoSblock.%d\n",ASSETCHAINS_SYMBOL,height,is_PoSblock); return(-1); } else @@ -2414,14 +2404,12 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in // the coinbase must pay the fees from the last transaction and the block reward at a minimum. if ( pblock->vtx.size() < 1 || pblock->vtx[0].vout.size() < 1 ) { - //fprintf(stderr, "[%s:%d] missing coinbase.\n", ASSETCHAINS_SYMBOL, height); - LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " missing coinbase.\n"); + fprintf(stderr, "[%s:%d] missing coinbase.\n", ASSETCHAINS_SYMBOL, height); return(-1); } else if ( pblock->vtx[0].vout[0].nValue < stakeTxValue ) { - //fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", ASSETCHAINS_SYMBOL, height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); - LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " coinbase vout0." << (long long)pblock->vtx[0].vout[0].nValue << " < blockreward+stakingtxfee." << (long long)stakeTxValue << std::endl); + fprintf(stderr, "[%s:%d] coinbase vout0.%lld < blockreward+stakingtxfee.%lld\n", ASSETCHAINS_SYMBOL, height, (long long)pblock->vtx[0].vout[0].nValue, (long long)stakeTxValue); return(-1); } // set the pindex->segid as this is now fully validated to be a PoS block. @@ -2482,8 +2470,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in // Check the notarisation tx is to the crypto address. if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 ) { - //fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height); - LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " notarisation is not to crypto address ht." << height << std::endl); + fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height); return(-1); } // Check min sigs. @@ -2491,8 +2478,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in numSN = komodo_notaries(notarypubkeys, height, pblock->nTime); if ( pblock->vtx[1].vin.size() < numSN/5 ) { - // fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%lld\n",height,numSN/5,(long long)pblock->vtx[1].vin.size()); - LOGSTREAM(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "[" << ASSETCHAINS_SYMBOL << ":" << height << "]" << " ht." << height << " does not meet minsigs." << numSN / 5 << " sigs." << (long long)pblock->vtx[1].vin.size() << std::endl); + fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%lld\n",height,numSN/5,(long long)pblock->vtx[1].vin.size()); return(-1); } } @@ -2591,7 +2577,7 @@ int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) pindex->newcoins = komodo_newcoins(&pindex->zfunds,&pindex->sproutfunds,pindex->GetHeight(),&block); else { - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "error loading block ht=" << pindex->GetHeight() << std::endl); + fprintf(stderr,"error loading block.%d\n",pindex->GetHeight()); return(0); } } @@ -2606,22 +2592,25 @@ int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) *sproutfundsp = sproutfunds; 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; - struct komodo_staking *newarray = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); - if (newarray == NULL) { - fprintf(stderr, "%s could not allocate memory\n", __func__); - return array; // prevent buf overflow, do not add utxo if no more mem allocated - } - array = newarray; + array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); //fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array); } kp = &array[(*numkp)++]; @@ -2642,13 +2631,11 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt { static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; int32_t PoSperc = 0, newStakerActive; - std::set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; + set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; uint64_t cbPerc = *utxovaluep, tocoinbase = 0; if (!EnsureWalletIsAvailable(0)) return 0; - - const bool needSpecialStakeUtxo = false; //conditions of contracts or params for which non-basic utxo for staking are needed - + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); assert(pwalletMain != NULL); *utxovaluep = 0; @@ -2671,9 +2658,9 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt LOCK(cs_main); CBlockIndex* pblockindex = chainActive[tipindex->GetHeight()]; CBlock block; CTxDestination addressout; - if (needSpecialStakeUtxo) + if ( ASSETCHAINS_MARMARA != 0 ) resetstaker = true; - else if ( ReadBlockFromDisk(block, pblockindex, 1) && komodo_isPoS(&block, nHeight, &addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) + else if ( ReadBlockFromDisk(block, pblockindex, 1) && komodo_isPoS(&block, nHeight, &addressout) != 0 && IsMine(*pwalletMain,addressout) != 0 ) { resetstaker = true; fprintf(stderr, "[%s:%d] Reset ram staker after mining a block!\n",ASSETCHAINS_SYMBOL,nHeight); @@ -2691,9 +2678,8 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt maxkp = numkp = 0; lasttime = 0; } - if (!needSpecialStakeUtxo) + if ( ASSETCHAINS_MARMARA == 0 ) { - // add normal staking UTXO: BOOST_FOREACH(const COutput& out, vecOutputs) { if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) @@ -2723,7 +2709,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt } } } - else + else { struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk; std::vector > unspentOutputs; @@ -2745,10 +2731,12 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt { array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey); } + // else fprintf(stderr,"SKIP addutxo %.8f numkp.%d vs max.%d\n",(double)nValue/COIN,numkp,maxkp); } } } lasttime = (uint32_t)time(NULL); + //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); } block_from_future_rejecttime = (uint32_t)GetTime() + ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX; for (i=winners=0; i 0 ) + signSuccess = true; + else signSuccess = false; + } if (!signSuccess) - LOGSTREAMFN(LOG_KOMODOBITCOIND, CCLOG_ERROR, stream << "failed to create signature\n"); + fprintf(stderr,"failed to create signature\n"); else *blocktimep = earliest; } diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index d88101a4213..cb170b921ec 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ -#pragma once + // komodo functions that interact with bitcoind C++ #include @@ -22,143 +22,97 @@ #include "komodo_defs.h" #include "script/standard.h" #include "cc/CCinclude.h" -#include "komodo_utils.h" // for OS_milliseconds() -#include + +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); +int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); +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); +unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); +bool EnsureWalletIsAvailable(bool avoidException); +extern bool fRequestShutdown; +extern CScript KOMODO_EARLYTXID_SCRIPTPUB; + +int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew); +uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht); +uint32_t komodo_heightstamp(int32_t height); + +//#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr)) struct MemoryStruct { char *memory; size_t size; }; 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) + + /************************************************************************ + * * Initialize the string handler so that it is thread safe - * @param s the string to initialize + * ************************************************************************/ -void init_string(return_string *s); + +void init_string(struct return_string *s); int tx_height( const uint256 &hash ); -// hash value to string for logging -static std::string hash2str(arith_uint256 hashval, int nbits); /************************************************************************ + * * Use the "writer" to accumulate text until done - * @param ptr - * @param size - * @param nmemb - * @param s - * @returns ?? + * + ************************************************************************/ + +size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s); + +/************************************************************************ + * + * return the current system time in milliseconds + * ************************************************************************/ -size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,return_string *s); #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 - * @param debugstr - * @param command - * @param rpcstr - * @param params - * @returns ?? + * ************************************************************************/ + char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params); #endif /************************************************************************ + * * perform the query - * @param retstrp pointer to return string - * @param debugstr - * @param url - * @param userpass - * @param command - * @param params - * @returns ?? + * ************************************************************************/ + char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params); -/**** - * @param ptr - * @param size - * @param nmemb - * @param data - * @returns size * nmemb - */ static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data); -/**** - * Do a POST using libcurl - * @param cHandlep curl handle - * @param url the address - * @param userpass - * @param postfields - * @param hdr1 - * @param hdr1 - * @param hdr2 - * @param hdr3 - * @returns the result of the POST - */ char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); -/*** - * Make an RPC call to the local daemon - * @param userpass - * @param method - * @param params - * @param port - * @returns results - */ char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port); -/**** - * @param dest the currency - * @param txidstr the txid desired - * @param kmdnotarized_heightp will be set to the KMD notarized height - * @returns txid height - */ int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); -int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 notarized_hash); +int32_t komodo_verifynotarizedscript(int32_t height,uint8_t *script,int32_t len,uint256 NOTARIZED_HASH); void komodo_reconsiderblock(uint256 blockhash); -int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 notarized_hash,uint256 notarized_desttxid); +int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t NOTARIZED_HEIGHT,uint256 NOTARIZED_HASH,uint256 NOTARIZED_DESTTXID); CScript komodo_makeopret(CBlock *pblock, bool fNew); -/*** - * Get seed - * @param height - * @returns seed for specified height - */ uint64_t komodo_seed(int32_t height); -/***** - * Get previous staking utxo opret, address and txtime - * @param opret - * @param valuep - * @param hash - * @param n - * @param destaddr - * @returns tx lock time - */ uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr); -/*** - * Get the block index - * @param hash - * @returns the block index for the specified hash - */ CBlockIndex *komodo_getblockindex(uint256 hash); -/***** - * Extension point to add preferences for stakes (dimxy) - * TODO: what if for some chain several chain's params require different multipliers. Which to select, max? - * @param tx - * @param nvout - * @returns multiplier - */ -static int32_t GetStakeMultiplier(CTransaction &tx, int32_t nvout); - - uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr); CScript EncodeStakingOpRet(uint256 merkleroot); @@ -175,9 +129,6 @@ bool komodo_hardfork_active(uint32_t time); uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); -// checks if block is PoS: -// last tx should point to the previous staking utxo (that is spent to self) -// returns 1 if this is PoS block and 0 if false int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout); void komodo_disconnect(CBlockIndex *pindex,CBlock& block); @@ -204,8 +155,7 @@ int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); 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); -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); +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); CBlockIndex *komodo_blockindex(uint256 hash); @@ -279,8 +229,17 @@ int64_t komodo_newcoins(int64_t *zfundsp,int64_t *sproutfundsp,int32_t nHeight,C int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height); -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); +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); -int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep, - uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); \ No newline at end of file +int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig, uint256 merkleroot); diff --git a/src/komodo_ccdata.cpp b/src/komodo_ccdata.cpp index f56c6a68f39..9346806093e 100644 --- a/src/komodo_ccdata.cpp +++ b/src/komodo_ccdata.cpp @@ -12,14 +12,12 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#include "komodo_globals.h" #include "komodo_ccdata.h" struct komodo_ccdata *CC_data; int32_t CC_firstheight; -uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); // in primitives/block.h +uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) { diff --git a/src/komodo_ccdata.h b/src/komodo_ccdata.h index 74a684f426f..939b0b98396 100644 --- a/src/komodo_ccdata.h +++ b/src/komodo_ccdata.h @@ -13,7 +13,6 @@ * * ******************************************************************************/ #pragma once - #include "komodo.h" uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); diff --git a/src/komodo_curve25519.cpp b/src/komodo_curve25519.cpp index 1d32fdbd450..389fcd643a3 100644 --- a/src/komodo_curve25519.cpp +++ b/src/komodo_curve25519.cpp @@ -1,6 +1,19 @@ -#include "komodo_utils.h" // for vcalc_sha256 - +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ #include "komodo_curve25519.h" +#include "komodo_utils.h" // for vcalc_sha256 void store_limb(uint8_t *out,uint64_t in) { @@ -21,6 +34,7 @@ bits320 fexpand(bits256 basepoint) return(out); } +#if __amd64__ // Multiply two numbers: output = in2 * in // output must be distinct to both inputs. The inputs are reduced coefficient form, the output is not. // Assumes that in[i] < 2**55 and likewise for in2. On return, output[i] < 2**52 @@ -112,6 +126,7 @@ bits256 curve25519(bits256 mysecret,bits256 basepoint) cmult(&x,&z,mysecret,bp); return(fcontract(fmul(x,crecip(z)))); } +#endif // Calculates nQ where Q is the x-coordinate of a point on the curve // resultx/resultz: the x coordinate of the resulting curve point (short form) @@ -144,6 +159,10 @@ void cmult(bits320 *resultx,bits320 *resultz,bits256 secret,const bits320 q) *resultx = *nqx, *resultz = *nqz; } +#ifndef _WIN32 +void OS_randombytes(unsigned char *x,long xlen); +#endif + bits256 rand256(int32_t privkeyflag) { bits256 randval; diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index aabb6a163f3..cfc631b9d3c 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -13,7 +13,6 @@ * * ******************************************************************************/ #pragma once -// derived from curve25519_donna #include #include @@ -52,18 +51,7 @@ static inline void fdifference_backwards(uint64_t *out,const uint64_t *in) void store_limb(uint8_t *out,uint64_t in); -static inline uint64_t load_limb(uint8_t *in) -{ - return - ((uint64_t)in[0]) | - (((uint64_t)in[1]) << 8) | - (((uint64_t)in[2]) << 16) | - (((uint64_t)in[3]) << 24) | - (((uint64_t)in[4]) << 32) | - (((uint64_t)in[5]) << 40) | - (((uint64_t)in[6]) << 48) | - (((uint64_t)in[7]) << 56); -} +static inline uint64_t load_limb(uint8_t *in); // Take a little-endian, 32-byte number and expand it into polynomial form bits320 fexpand(bits256 basepoint); @@ -766,10 +754,6 @@ inline bits320 crecip(const bits320 z) /* 2^255 - 21 */ return(fmul(t0, a)); } -#ifndef _WIN32 -void OS_randombytes(unsigned char *x,long xlen); -#endif - bits256 rand256(int32_t privkeyflag); bits256 curve25519_basepoint9(); diff --git a/src/komodo_cutils.h b/src/komodo_cutils.h new file mode 100644 index 00000000000..3fb5711b1cb --- /dev/null +++ b/src/komodo_cutils.h @@ -0,0 +1,81 @@ +#pragma once +#include +#include +#include + +#ifndef _BITS256 +#define _BITS256 +union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; +typedef union _bits256 bits256; +#endif + +int32_t _unhex(char c) +{ + if ( c >= '0' && c <= '9' ) + return(c - '0'); + else if ( c >= 'a' && c <= 'f' ) + return(c - 'a' + 10); + else if ( c >= 'A' && c <= 'F' ) + return(c - 'A' + 10); + return(-1); +} + +int32_t unhex(char c) +{ + int32_t hex; + if ( (hex= _unhex(c)) < 0 ) + { + //printf("unhex: illegal hexchar.(%c)\n",c); + } + return(hex); +} + +int32_t is_hexstr(char *str,int32_t n) +{ + int32_t i; + if ( str == 0 || str[0] == 0 ) + return(0); + for (i=0; str[i]!=0; i++) + { + if ( n > 0 && i >= n ) + break; + if ( _unhex(str[i]) < 0 ) + break; + } + if ( n == 0 ) + return(i); + return(i == n); +} + +unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } + +int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) +{ + int32_t adjust,i = 0; + //printf("decode.(%s)\n",hex); + if ( is_hexstr(hex,n) <= 0 ) + { + memset(bytes,0,n); + return(n); + } + if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) + hex[--n] = 0; + if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) + { + if ( n > 0 ) + { + bytes[0] = unhex(hex[0]); + printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); + } + bytes++; + hex++; + adjust = 1; + } else adjust = 0; + if ( n > 0 ) + { + for (i=0; itype ) @@ -138,13 +128,6 @@ void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) } } -/**** - * Roll backwards through the list of events, undoing them - * NOTE: The heart of this calls komodo_event_undo, which only lowers the sp->SAVEDHEIGHT - * @param sp the state - * @param symbol the symbol - * @param height the height - */ void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) { struct komodo_event *ep; @@ -160,23 +143,16 @@ void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) { if ( (ep= sp->Komodo_events[sp->Komodo_numevents-1]) != 0 ) { - if ( ep->height < height ) // don't go lower than the passed-in height + if ( ep->height < height ) break; //printf("[%s] undo %s event.%c ht.%d for rewind.%d\n",ASSETCHAINS_SYMBOL,symbol,ep->type,ep->height,height); komodo_event_undo(sp,ep); sp->Komodo_numevents--; - // Q: When are these events deallocated? } } } } -/** - * Set the SAVEDHEIGHT and CURRENT_HEIGHT if higher than what is in the state object - * @param sp the state - * @param kmdheight the desired kmdheight - * @param timestamp the timestamp - */ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp) { if ( sp != 0 ) @@ -191,15 +167,6 @@ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t time } } -/**** - * Add a new height - * NOTE: If kmdheight is a negative number, it will cause a rewind event to abs(kmdheight) - * @param sp the state - * @param symbol the symbol - * @param height the height - * @param kmdheight the kmdheight to add - * @param timestamp the timestamp - */ void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp) { uint32_t buf[2]; diff --git a/src/komodo_events.h b/src/komodo_events.h index 62462095d08..bfbf9c27918 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -13,61 +13,23 @@ * * ******************************************************************************/ #pragma once - #include "komodo_defs.h" -#include "komodo.h" +#include "komodo_structs.h" -struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen); +komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen); -void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash, - uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth); +void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth); -/**** - * Add a pubkey event to state - * @param sp the state - * @param symbol the symbol - * @param height - * @param num - * @param pubkeys - */ void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]); void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num); void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen); -/*** - * Undo an event - * NOTE: Jut rolls back the height if a KMDHEIGHT, otherwise does nothing - * @param sp the state - * @param ep the event - */ void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep); -/**** - * Roll backwards through the list of events, undoing them - * NOTE: The heart of this calls komodo_event_undo, which only lowers the sp->SAVEDHEIGHT - * @param sp the state - * @param symbol the symbol - * @param height the height - */ void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); -/** - * Set the SAVEDHEIGHT and CURRENT_HEIGHT if higher than what is in the state object - * @param sp the state - * @param kmdheight the desired kmdheight - * @param timestamp the timestamp - */ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp); -/**** - * Add a new height - * NOTE: If kmdheight is a negative number, it will cause a rewind event to abs(kmdheight) - * @param sp the state - * @param symbol the symbol - * @param height the height - * @param kmdheight the kmdheight to add - * @param timestamp the timestamp - */ void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp); diff --git a/src/komodo_gateway.cpp b/src/komodo_gateway.cpp index 0361443b895..96f2e5d6b24 100644 --- a/src/komodo_gateway.cpp +++ b/src/komodo_gateway.cpp @@ -1,4 +1,3 @@ - /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -13,10 +12,10 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ -#include "komodo.h" // for komodo_parsestatefile -#include "komodo_globals.h" - #include "komodo_gateway.h" +#include "komodo_utils.h" // komodo_stateptrget + +int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx); int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) { @@ -398,22 +397,6 @@ uint64_t komodo_paxtotal() return(total); } -static int _paxorder(const void *a,const void *b) -{ -#define pax_a (*(struct pax_transaction **)a) -#define pax_b (*(struct pax_transaction **)b) - uint64_t aval,bval; - aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height; - bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height; - if ( bval > aval ) - return(-1); - else if ( bval < aval ) - return(1); - return(0); -#undef pax_a -#undef pax_b -} - int32_t komodo_pending_withdraws(char *opretstr) // todo: enforce deterministic order { struct pax_transaction *pax,*pax2,*tmp,*paxes[64]; uint8_t opretbuf[16384*4]; int32_t i,n,ht,len=0; uint64_t total = 0; @@ -727,6 +710,14 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim } } } + if ( height > 0 && ASSETCHAINS_MARMARA != 0 && (height & 1) == 0 ) + { + if ( MarmaraValidateCoinbase(height,block.vtx[0]) < 0 ) + { + fprintf(stderr,"MARMARA error ht.%d constrains even height blocks to pay 100%% to CC in vout0 with opreturn\n",height); + return(-1); + } + } // we don't want these checks in VRSC, leave it at the Sapling upgrade if ( ASSETCHAINS_SYMBOL[0] == 0 || ((ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1) || @@ -817,17 +808,6 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim return(0); } -/*** - * handle an opreturn - * @param height the height - * @param value the value - * @param opretbuf the buffer - * @param opretlen the length of the buffer - * @param txid - * @param vout - * @param source - * @returns result (i.e. "unknown", "assetchain", "kv", ect. - */ const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source) { uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,kvheight,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fee,fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff; @@ -1243,19 +1223,12 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ printf("numR.%d numV.%d numN.%d count.%d\n",numR,numV,numN,count); /*else if ( func == 'K' ) // KMD height: stop after 1st else if ( func == 'T' ) // KMD height+timestamp: stop after 1st + else if ( func == 'N' ) // notarization, scan backwards 1440+ blocks; else if ( func == 'V' ) // price feed: can stop after 1440+ else if ( func == 'R' ) // opreturn:*/ } -/**** - * Load file contents into buffer - * @param fname the filename - * @param bufp the buffer that will contain the file contents - * @param lenp the length of the file - * @param allocsizep the buffer size allocated - * @returns the file contents - */ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) { FILE *fp; @@ -1270,7 +1243,7 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) { fclose(fp); *lenp = 0; - //printf("OS_loadfile null size.(%s)\n",fname); + printf("OS_loadfile null size.(%s)\n",fname); return(0); } if ( filesize > buflen ) @@ -1294,17 +1267,9 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) return(buf); } -/*** - * Get file contents - * @param allocsizep the size allocated for the file contents (NOTE: this will probably be 64 bytes larger than the file size) - * @param fname the file name - * @returns the data from the file - */ uint8_t *OS_fileptr(long *allocsizep,char *fname) { - long filesize = 0; // the size of the file - uint8_t *buf = 0; // a pointer to the buffer - void *retptr; // the return pointer (points to buf) + long filesize = 0; uint8_t *buf = 0; void *retptr; *allocsizep = 0; retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); return((uint8_t *)retptr); @@ -1374,33 +1339,12 @@ long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long return(newfpos); } -/*** - * Initialize state from the filesystem - * @param sp the state to initialize - * @param fname the filename - * @param symbol - * @param dest - * @returns -1 on error, 1 on success - */ int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest) { - FILE *indfp; // an index file that will be created - char indfname[1024]; // the filename of the index file - uint8_t *filedata; // data read from the file fname - long validated=-1; // not used - long datalen; // length of the data read from fname plus a little more - long fpos; // where we are reading in filedata - long lastfpos; // not used - uint32_t tmp; // not used - uint32_t prevpos100; // position to be written in index file - uint32_t indcounter; // position within index file - uint32_t starttime = (uint32_t)time(NULL); - int32_t func; // record type - int32_t finished = 0; // boolean, true if file has been read successfully - - safecopy(indfname,fname,sizeof(indfname)-4); // truncate 4 characters from filename + FILE *indfp; char indfname[1024]; uint8_t *filedata; long validated=-1,datalen,fpos,lastfpos; uint32_t tmp,prevpos100,indcounter,starttime; int32_t func,finished = 0; + starttime = (uint32_t)time(NULL); + safecopy(indfname,fname,sizeof(indfname)-4); strcat(indfname,".ind"); - if ( (filedata= OS_fileptr(&datalen,fname)) != 0 ) { if ( 1 )//datalen >= (1LL << 32) || GetArg("-genind",0) != 0 || (validated= komodo_stateind_validate(0,indfname,filedata,datalen,&prevpos100,&indcounter,symbol,dest)) < 0 ) @@ -1614,42 +1558,6 @@ void komodo_passport_iteration() } } - -extern std::vector Mineropret; // opreturn data set by the data gathering code -#define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% -#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR -#define KOMODO_LOCALPRICE_CACHESIZE 13 -#define KOMODO_MAXPRICES 2048 -#define PRICES_SMOOTHWIDTH 1 - -#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) - -/* -const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) -// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" -const char *Forex[] = -{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" -}; // must be in ECB list -*/ - -struct komodo_extremeprice -{ - uint256 blockhash; - uint32_t pricebits,timestamp; - int32_t height; - int16_t dir,ind; -} ExtremePrice; - -struct komodo_priceinfo -{ - FILE *fp; - char symbol[PRICES_MAXNAMELENGTH]; // TODO: it was 64 -} PRICES[KOMODO_MAXPRICES]; - -uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; -int64_t PriceMult[KOMODO_MAXPRICES]; -int32_t komodo_cbopretsize(uint64_t flags); - void komodo_PriceCache_shift() { int32_t i; @@ -1729,14 +1637,14 @@ uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t } // komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance -int32_t komodo_pricecmp(int32_t nHeight, char *maxflags, uint32_t *pricebitsA, uint32_t *pricebitsB, int32_t begin, int32_t end, int64_t tolerance) +int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance) { int32_t i; uint32_t newprice; - for (i = begin; i < end; i++) + for (i=1; i newprice.%u out of tolerance maxflag.%d\n", nHeight, i, end, pricebitsB[i], pricebitsA[i], newprice, maxflags[i]); + fprintf(stderr,"ht.%d i.%d/%d %u vs %u -> newprice.%u out of tolerance maxflag.%d\n",nHeight,i,n,pricebitsB[i],pricebitsA[i],newprice,maxflags[i]); return(-1); } } @@ -1744,18 +1652,15 @@ int32_t komodo_pricecmp(int32_t nHeight, char *maxflags, uint32_t *pricebitsA, u } // komodo_priceclamp() clamps any price that is beyond tolerance -int32_t komodo_priceclamp(uint32_t *pricebits, uint32_t *refprices, int32_t begin, int32_t end, int64_t tolerance) +int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance) { - int32_t i; - uint32_t newprice; - char maxflags[KOMODO_MAXPRICES]; - - memset(maxflags, 0, sizeof(maxflags)); - for (i = begin; i < end; i++) + int32_t i; uint32_t newprice; char maxflags[KOMODO_MAXPRICES]; + memset(maxflags,0,sizeof(maxflags)); + for (i=1; i %u\n", i, end, refprices[i], pricebits[i], newprice); + fprintf(stderr,"priceclamped[%d of %d] %u vs %u -> %u\n",i,n,refprices[i],pricebits[i],newprice); pricebits[i] = newprice; } } @@ -1765,76 +1670,56 @@ int32_t komodo_priceclamp(uint32_t *pricebits, uint32_t *refprices, int32_t begi // komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight CScript komodo_mineropret(int32_t nHeight) { - CScript opret; - char maxflags[KOMODO_MAXPRICES]; - uint32_t pricebits[KOMODO_MAXPRICES], prevbits[KOMODO_MAXPRICES]; - int32_t maxflag, i, n, numzero = 0; - - if (Mineropret.size() >= PRICES_SIZEBIT0) + CScript opret; char maxflags[KOMODO_MAXPRICES]; uint32_t pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES]; int32_t maxflag,i,n,numzero=0; + if ( Mineropret.size() >= PRICES_SIZEBIT0 ) { n = (int32_t)(Mineropret.size() / sizeof(uint32_t)); numzero = 1; - while (numzero > 0) + while ( numzero > 0 ) { - memcpy(pricebits, Mineropret.data(), Mineropret.size()); - for (i = numzero = 0; i < n; i++) - { - if (pricebits[i] == 0) + memcpy(pricebits,Mineropret.data(),Mineropret.size()); + for (i=numzero=0; i processors; - PricesFeedGetCustomProcessors(processors); - - if (komodo_heightpricebits(0, prevbits, nHeight - 1) > 0) // get previous prices + if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 ) { - // set working prices buffer: - memcpy(pricebits, Mineropret.data(), Mineropret.size()); - memset(maxflags, 0, sizeof(maxflags)); - - for (auto const &p : processors) + memcpy(pricebits,Mineropret.data(),Mineropret.size()); + memset(maxflags,0,sizeof(maxflags)); + if ( komodo_pricecmp(0,n,maxflags,pricebits,prevbits,PRICES_ERRORRATE) < 0 ) { - if (p.clamper == NULL) - { - // default clamper - if (komodo_pricecmp(nHeight, maxflags, pricebits, prevbits, p.b, p.e, PRICES_ERRORRATE) < 0) - { - // if the new prices are outside tolerance, update Mineropret with clamped prices - komodo_priceclamp(pricebits, prevbits, p.b, p.e, PRICES_ERRORRATE); - //fprintf(stderr,"update Mineropret to clamped prices\n"); - - } - } - else - p.clamper(nHeight, pricebits, prevbits, p.b, p.e, PRICES_ERRORRATE); + // if the new prices are outside tolerance, update Mineropret with clamped prices + komodo_priceclamp(n,pricebits,prevbits,PRICES_ERRORRATE); + //fprintf(stderr,"update Mineropret to clamped prices\n"); + memcpy(Mineropret.data(),pricebits,Mineropret.size()); } - - // copy working buffer back: - memcpy(Mineropret.data(), pricebits, Mineropret.size()); } - int32_t i; - for (i = 0; i < Mineropret.size(); i++) - fprintf(stderr, "%02x", Mineropret[i]); - fprintf(stderr, " <- Mineropret\n"); + for (i=0; i vopret; - char maxflags[KOMODO_MAXPRICES]; - uint256 bhash; double btcusd, btcgbp, btceur; - uint32_t localbits[KOMODO_MAXPRICES], pricebits[KOMODO_MAXPRICES], prevbits[KOMODO_MAXPRICES], newprice; - int32_t prevtime, lag, lag2, lag3, n, errflag, iter; - uint32_t now; - const int PRICES_EARLY_CHAIN_HEIGHT = 1000; - - - if (ASSETCHAINS_CBOPRET != 0 && nHeight > 0) + std::vector vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; + now = (uint32_t)time(NULL); + if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) { - now = (uint32_t)time(NULL); bhash = block->GetHash(); - GetOpReturnData(scriptPubKey, vopret); - if (vopret.size() >= PRICES_SIZEBIT0) + GetOpReturnData(scriptPubKey,vopret); + if ( vopret.size() >= PRICES_SIZEBIT0 ) { - // default prices validation: n = (int32_t)(vopret.size() / sizeof(uint32_t)); - memcpy(pricebits, vopret.data(), Mineropret.size()); - - if (nHeight > 2) + memcpy(pricebits,vopret.data(),Mineropret.size()); + memset(maxflags,0,sizeof(maxflags)); + if ( nHeight > 2 ) { - if (komodo_heightpricebits(0, prevbits, nHeight - 1) <= 0) - { - std::cerr << __func__ << " error: could not get prevbits for height " << nHeight-1 << std::endl; - return -1; - } - - std::vector processors; - PricesFeedGetCustomProcessors(processors); - - std::vector< std::pair > ranges; - for (const auto &p : processors) - { - if (p.validator) - { - // call the custom validator - if (p.validator(nHeight, ASSETCHAINS_BLOCKTIME, block->nTime, previndex->nTime, pricebits, prevbits, p.b, p.e) < 0) - std::cerr << __func__ << " error: custom validation function invalidated prices data for prices indexes from " << p.b << " to " << p.e << std::endl; - } - else - { - // create ranges for the default validation: - ranges.push_back(std::make_pair(p.b, p.e)); - } - } - - // proceed with the default validation: - memset(maxflags, 0, sizeof(maxflags)); prevtime = previndex->nTime; lag = (int32_t)(now - pricebits[0]); lag2 = (int32_t)(pricebits[0] - prevtime); lag3 = (int32_t)(block->nTime - pricebits[0]); - - if (lag < -60) // avoid data from future + if ( lag < -60 ) // avoid data from future { - fprintf(stderr, "A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n", nHeight, now, prevtime, block->nTime, pricebits[0], lag, lag2, lag3); + fprintf(stderr,"A ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); return(-1); } - // we should allow lag2 check to pass for early chains - // currently minimum prices update interval = 120 sec (really 120..130) - // suppose blocktime = 180 sec - // block[i], t = T0 - // block[i+1], t = T0+180 - // earliest update t <= T0+180-130 <= T0+50 - // so lag2 could be not less than +50 on mature chain with blocktime = 180 - // but on the initial chain stage blocks could be generated faster, in several secs (> 10 sec) - // block[i], t = T0 - // block[i+1], t = T0+10 - // earliest Tupdate <= T0+10-130 <= T0-120 - // as lag2 could be even -120 for blocks per 10 sec let's allow lag2 to be not less than -130 for early chains - if (lag2 < -60 && nHeight >= PRICES_EARLY_CHAIN_HEIGHT || lag2 < -130) //testchain_exemption ) // must be close to last block timestamp + if ( lag2 < -60 ) //testchain_exemption ) // must be close to last block timestamp { - fprintf(stderr, "B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n", nHeight, now, prevtime, block->nTime, pricebits[0], lag, lag2, lag3, ASSETCHAINS_BLOCKTIME, lag2 < -ASSETCHAINS_BLOCKTIME); - if (nHeight > testchain_exemption) + fprintf(stderr,"B ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d vs %d cmp.%d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3,ASSETCHAINS_BLOCKTIME,lag2<-ASSETCHAINS_BLOCKTIME); + if ( nHeight > testchain_exemption ) return(-1); } - - // explanation for lag3: - // lag3 < -60 check violation could be possible if a validation node has clock sync problems - // lag3 > ASSETCHAINS_BLOCKTIME could be possible if update interval is more than blocktime: - // block[i] t = T0 - // block[i+1] t = T0+180 - // earliest update t = T0+180-130 = T0+50 - // lag3 = 130, this is less than min blocktime = 180 - // (on early chains this also will work as we check ASSETCHAINS_BLOCKTIME param value and not real early block generation time) - if (lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME) + if ( lag3 < -60 || lag3 > ASSETCHAINS_BLOCKTIME ) { - fprintf(stderr, "C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n", nHeight, now, prevtime, block->nTime, pricebits[0], lag, lag2, lag3); - if (nHeight > testchain_exemption) + fprintf(stderr,"C ht.%d now.%u htstamp.%u %u - pricebits[0] %u -> lags.%d %d %d\n",nHeight,now,prevtime,block->nTime,pricebits[0],lag,lag2,lag3); + if ( nHeight > testchain_exemption ) return(-1); } - - // basic price values (always present in config): - btcusd = (double)pricebits[1] / 10000; - btcgbp = (double)pricebits[2] / 10000; - btceur = (double)pricebits[3] / 10000; - fprintf(stderr, "ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n", nHeight, lag, btcusd, btcgbp, btceur, btcusd / btcgbp, btcusd / btceur, btcgbp / btceur, lag2); - - if (nHeight < testchain_exemption) + btcusd = (double)pricebits[1]/10000; + btcgbp = (double)pricebits[2]/10000; + btceur = (double)pricebits[3]/10000; + fprintf(stderr,"ht.%d: lag.%d %.4f USD, %.4f GBP, %.4f EUR, GBPUSD %.6f, EURUSD %.6f, EURGBP %.6f [%d]\n",nHeight,lag,btcusd,btcgbp,btceur,btcusd/btcgbp,btcusd/btceur,btcgbp/btceur,lag2); + if ( komodo_heightpricebits(0,prevbits,nHeight-1) > 0 ) { - // set for a test chain - for (auto const &r : ranges) { - for (int32_t i = r.first; i < r.second; i++) - if (pricebits[i] == 0) + if ( nHeight < testchain_exemption ) + { + for (i=0; i= PRICES_SIZEBIT0) + } else return(-1); + if ( lag < ASSETCHAINS_BLOCKTIME && Mineropret.size() >= PRICES_SIZEBIT0 ) { - memcpy(localbits, Mineropret.data(), Mineropret.size()); - if (nHeight < testchain_exemption) + memcpy(localbits,Mineropret.data(),Mineropret.size()); + if ( nHeight < testchain_exemption ) { - // set for a test chain - for (auto const &r : ranges) { - for (int32_t i = r.first; i < r.second; i++) - if (localbits[i] == 0) - localbits[i] = prevbits[i]; - } - localbits[0] = prevbits[0]; // store timestamp + for (i=0; i 0 && localbits[i] < prevbits[i] ) { - // make sure local price is moving in right direction - fprintf(stderr, "maxflag.%d i.%d localbits.%u vs pricebits.%u prevbits.%u\n", maxflag, i, localbits[i], pricebits[i], prevbits[i]); - if (maxflag > 0 && localbits[i] < prevbits[i]) - { - if (iter == 0) { - checked = true; - break; - } - // second iteration checks recent prices to see if within local volatility - int32_t icache; - for (icache = 0; icache < KOMODO_LOCALPRICE_CACHESIZE; icache++) + if ( iter == 0 ) + break; + // second iteration checks recent prices to see if within local volatility + for (j=0; j= prevbits[i] ) { - if (PriceCache[icache][i] >= prevbits[i]) - { - fprintf(stderr, "i.%d within recent localprices[%d] %u >= %u\n", i, icache, PriceCache[icache][i], prevbits[i]); - checked = true; - break; - } - } - if (icache == KOMODO_LOCALPRICE_CACHESIZE) - { - komodo_queuelocalprice(1, nHeight, block->nTime, bhash, i, prevbits[i]); - checked = true; + fprintf(stderr,"i.%d within recent localprices[%d] %u >= %u\n",i,j,PriceCache[j][i],prevbits[i]); break; } - } - else if (maxflag < 0 && localbits[i] > prevbits[i]) + if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - if (iter == 0) { - checked = true; - break; - } - int32_t icache; - for (icache = 0; icache < KOMODO_LOCALPRICE_CACHESIZE; icache++) - { - if (PriceCache[icache][i] <= prevbits[i]) - { - fprintf(stderr, "i.%d within recent localprices[%d] %u <= prev %u\n", i, icache, PriceCache[icache][i], prevbits[i]); - checked = true; - break; - } - } - if (icache == KOMODO_LOCALPRICE_CACHESIZE) + komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]); + break; + } + } + else if ( maxflag < 0 && localbits[i] > prevbits[i] ) + { + if ( iter == 0 ) + break; + for (j=0; jnTime, bhash, i, prevbits[i]); - checked = true; + fprintf(stderr,"i.%d within recent localprices[%d] %u <= prev %u\n",i,j,PriceCache[j][i],prevbits[i]); break; } + if ( j == KOMODO_LOCALPRICE_CACHESIZE ) + { + komodo_queuelocalprice(-1,nHeight,block->nTime,bhash,i,prevbits[i]); + break; } } } - if (checked) - break; // break from ranges } - if (checked) + if ( i != n ) { - if (iter == 0) + if ( iter == 0 ) { - fprintf(stderr, "force update prices\n"); + fprintf(stderr,"force update prices\n"); komodo_cbopretupdate(1); - memcpy(localbits, Mineropret.data(), Mineropret.size()); - } - else - { - std::cerr << __func__ << " prices opreturn not valid" << std::endl; - return(-1); - } + memcpy(localbits,Mineropret.data(),Mineropret.size()); + } else return(-1); } } } } - if (bhash == ExtremePrice.blockhash) + if ( bhash == ExtremePrice.blockhash ) { - fprintf(stderr, "approved a previously extreme price based on new data ht.%d vs %u vs %u\n", ExtremePrice.height, ExtremePrice.timestamp, (uint32_t)block->nTime); - memset(&ExtremePrice, 0, sizeof(ExtremePrice)); + fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime); + memset(&ExtremePrice,0,sizeof(ExtremePrice)); } return(0); - } - else - fprintf(stderr, "wrong (too big) prices opreturn size %d vs %d, scriptPubKey size %d [%02x]\n", (int32_t)vopret.size(), (int32_t)Mineropret.size(), (int32_t)scriptPubKey.size(), (scriptPubKey.size() > 0 ? scriptPubKey[0] : '\0')); + } else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]); return(-1); } return(0); @@ -2198,32 +1973,167 @@ const char *Techstocks[] = { "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN" }; const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; + const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; */ cJSON *get_urljson(char *url) { - char *jsonstr; - cJSON *json = 0; + char *jsonstr; cJSON *json = 0; if ( (jsonstr= issue_curl(url)) != 0 ) { //fprintf(stderr,"(%s) -> (%s)\n",url,jsonstr); json = cJSON_Parse(jsonstr); - //free(jsonstr); - cJSON_free(jsonstr); + free(jsonstr); } return(json); } +int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector symbols) +{ + char url[32768],*symbol,*timestr; cJSON *json,*obj; int32_t i,n=0,retval=-1; uint32_t uprice,timestamp; + sprintf(url,"https://api.iextrading.com/1.0/tops/last?symbols=%s",GetArg("-ac_stocks","").c_str()); + fprintf(stderr,"url.(%s)\n",url); + if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"iex")) != 0 ) // + { + fprintf(stderr,"stocks.(%s)\n",jprint(json,0)); + if ( (n= cJSON_GetArraySize(json)) > 0 ) + { + retval = n; + for (i=0; i now+60 || timestamp < now-ASSETCHAINS_BLOCKTIME ) + { + fprintf(stderr,"time error.%d (%u vs %u)\n",timestamp-now,timestamp,now); + retval = -1; + }*/ + if ( symbols[i] != symbol ) + { + retval = -1; + fprintf(stderr,"MISMATCH."); + } + fprintf(stderr,"(%s %u) ",symbol,uprice); + } + } + fprintf(stderr,"numstocks.%d\n",n); + } + //https://api.iextrading.com/1.0/tops/last?symbols=AAPL -> [{"symbol":"AAPL","price":198.63,"size":100,"time":1555092606076}] + free_json(json); + } + return(retval); +} + +uint32_t get_dailyfx(uint32_t *prices) +{ + //{"base":"USD","rates":{"BGN":1.74344803,"NZD":1.471652701,"ILS":3.6329113924,"RUB":65.1997682296,"CAD":1.3430201462,"USD":1.0,"PHP":52.8641469068,"CHF":0.9970582992,"AUD":1.4129078267,"JPY":110.6792654662,"TRY":5.6523444464,"HKD":7.8499732573,"MYR":4.0824567659,"HRK":6.6232840078,"CZK":22.9862720628,"IDR":14267.4986628633,"DKK":6.6551078624,"NOK":8.6806917454,"HUF":285.131039401,"GBP":0.7626582278,"MXN":19.4183455161,"THB":31.8702085933,"ISK":122.5708682475,"ZAR":14.7033339276,"BRL":3.9750401141,"SGD":1.3573720806,"PLN":3.8286682118,"INR":69.33187734,"KRW":1139.1602781244,"RON":4.2423783206,"CNY":6.7387234801,"SEK":9.3385630237,"EUR":0.8914244963},"date":"2019-03-28"} + char url[512],*datestr; cJSON *json,*rates; int32_t i; uint32_t datenum=0,price = 0; + sprintf(url,"https://api.openrates.io/latest?base=USD"); + if ( (json= get_urljson(url)) != 0 ) //if ( (json= send_curl(url,(char *)"dailyfx")) != 0 ) + { + if ( (rates= jobj(json,(char *)"rates")) != 0 ) + { + for (i=0; i strvec) +{ + int32_t i,errs=0; uint32_t price; char *symbol; + for (i=0; i 333 ) // for debug only! +// ASSETCHAINS_CBOPRET = 7; + size = komodo_cbopretsize(ASSETCHAINS_CBOPRET); + if ( Mineropret.size() < size ) + Mineropret.resize(size); + size = PRICES_SIZEBIT0; + if ( (forceflag != 0 || now > lastbtc+120) && get_btcusd(pricebits) == 0 ) + { + if ( flags == 0 ) + komodo_PriceCache_shift(); + memcpy(PriceCache[0],pricebits,PRICES_SIZEBIT0); + flags |= 1; } - - if (count > 0) { - komodo_PriceCache_shift(); - memcpy(PriceCache[0], pricebuf, count * sizeof(uint32_t)); - flags = 1; //old code compatibility + if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) + { + if ( now > lasttime+3600*5 || forexprices[0] == 0 ) // cant assume timestamp is valid for forex price as it is a daily weekday changing thing anyway. + { + get_dailyfx(forexprices); + if ( flags == 0 ) + komodo_PriceCache_shift(); + flags |= 2; + memcpy(&PriceCache[0][size/sizeof(uint32_t)],forexprices,sizeof(forexprices)); + } + size += (sizeof(Forex)/sizeof(*Forex)) * sizeof(uint32_t); + } + if ( (ASSETCHAINS_CBOPRET & 4) != 0 ) + { + if ( forceflag != 0 || flags != 0 ) + { + get_cryptoprices(pricebuf,Cryptos,(int32_t)(sizeof(Cryptos)/sizeof(*Cryptos)),ASSETCHAINS_PRICES); + if ( flags == 0 ) + komodo_PriceCache_shift(); + memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,(sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t)); + flags |= 4; // very rarely we can see flags == 6 case + } + size += (sizeof(Cryptos)/sizeof(*Cryptos)+ASSETCHAINS_PRICES.size()) * sizeof(uint32_t); + } + now = (uint32_t)time(NULL); + if ( (ASSETCHAINS_CBOPRET & 8) != 0 ) + { + if ( forceflag != 0 || flags != 0 ) + { + if ( get_stockprices(now,pricebuf,ASSETCHAINS_STOCKS) == ASSETCHAINS_STOCKS.size() ) + { + if ( flags == 0 ) + komodo_PriceCache_shift(); + memcpy(&PriceCache[0][size/sizeof(uint32_t)],pricebuf,ASSETCHAINS_STOCKS.size() * sizeof(uint32_t)); + flags |= 8; // very rarely we can see flags == 10 case + } + } + size += (ASSETCHAINS_STOCKS.size()) * sizeof(uint32_t); } - if ( flags != 0 ) { - uint32_t opretsize = komodo_cbopretsize(ASSETCHAINS_CBOPRET); - if (Mineropret.size() < opretsize) - Mineropret.resize(opretsize); - -// if ( (flags & 1) != 0 ) -// lastbtc = now; -// if ( (flags & 2) != 0 ) -// lasttime = now; - memcpy(Mineropret.data(), PriceCache[0], opretsize); - - // invalidate block with extreme prices: - if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < count && now < ExtremePrice.timestamp+3600 ) + if ( (flags & 1) != 0 ) + lastbtc = now; + if ( (flags & 2) != 0 ) + lasttime = now; + memcpy(Mineropret.data(),PriceCache[0],size); + if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 ) { fprintf(stderr,"cmp dir.%d PriceCache[0][ExtremePrice.ind] %u >= %u ExtremePrice.pricebits\n",ExtremePrice.dir,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) @@ -2303,20 +2239,35 @@ void komodo_cbopretupdate(int32_t forceflag) //fprintf(stderr," <- set Mineropret[%d] size.%d %ld\n",(int32_t)Mineropret.size(),size,sizeof(PriceCache[0])); } } - pending = 0; // allow entry to the function + pending = 0; } -// get multiplier to normalize prices to 100,000,000 decimal order, to make synthetic indexes -int64_t komodo_pricemult_to10e8(int32_t ind) +int64_t komodo_pricemult(int32_t ind) { int32_t i,j; if ( (ASSETCHAINS_CBOPRET & 1) != 0 && ind < KOMODO_MAXPRICES ) { - int64_t conversionmult = PricesFeedMultiplier(ind); - if (conversionmult >= 1) - return COIN / conversionmult; - else - return COIN; // this should not happen + if ( PriceMult[0] == 0 ) + { + for (i=0; i<4; i++) + PriceMult[i] = 10000; + if ( (ASSETCHAINS_CBOPRET & 2) != 0 ) + { + for (j=0; j= KOMODO_MAXPRICES ) return(-1); - mult = komodo_pricemult_to10e8(ind); + mult = komodo_pricemult(ind); if ( nonzprices != 0 ) memset(nonzprices,0,sizeof(*nonzprices)*PRICES_DAYWINDOW); //for (i=0; i maxcorrelation ) maxcorrelation = correlation; } - //fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice); + fprintf(stderr,"ind.%d iter.%d maxcorrelation.%d ref.%llu high.%llu low.%llu\n",ind,iter,maxcorrelation,(long long)refprice,(long long)highprice,(long long)lowprice); return(0); } @@ -2520,36 +2519,6 @@ void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters) } else memcpy(dest,src,width*sizeof(*dest)); } -// http://www.holoborodko.com/pavel/numerical-methods/noise-robust-smoothing-filter/ -//const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 }; -static int cmp_llu(const void *a, const void*b) -{ - if(*(int64_t *)a < *(int64_t *)b) return -1; - else if(*(int64_t *)a > *(int64_t *)b) return 1; - else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism - return(-1); - else return(1); -} - -static void sort64(int64_t *l, int32_t llen) -{ - qsort(l,llen,sizeof(uint64_t),cmp_llu); -} - -static int revcmp_llu(const void *a, const void*b) -{ - if(*(int64_t *)a < *(int64_t *)b) return 1; - else if(*(int64_t *)a > *(int64_t *)b) return -1; - else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism - return(-1); - else return(1); -} - -static void revsort64(int64_t *l, int32_t llen) -{ - qsort(l,llen,sizeof(uint64_t),revcmp_llu); -} - int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip) { int32_t i,dir=0; int64_t sum=0,nonzprice,price,halfave,thirdave,fourthave,decayprice; @@ -2714,11 +2683,11 @@ void komodo_pricesupdate(int32_t height,CBlock *pblock) } else fprintf(stderr,"error price_smoothed ht.%d ind.%d\n",height,ind); } else fprintf(stderr,"error fread ptr64 for ht.%d ind.%d\n",height,ind); } - } //else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind); + } else fprintf(stderr,"error komodo_pricecorrelated for ht.%d ind.%d\n",height,ind); } - //fprintf(stderr,"height.%d\n",height); + fprintf(stderr,"height.%d\n",height); } else fprintf(stderr,"error reading rawprices for ht.%d\n",height); - } // else fprintf(stderr,"height.%d <= width.%d\n",height,width); + } else fprintf(stderr,"height.%d <= width.%d\n",height,width); pthread_mutex_unlock(&pricemutex); } else fprintf(stderr,"null PRICES[0].fp\n"); } else fprintf(stderr,"numprices mismatch, height.%d\n",height); @@ -2737,38 +2706,3 @@ int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblo pthread_mutex_unlock(&pricemutex); return(retval); } - -// place to add miner's created transactions -UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey &mypk); - -void komodo_createminerstransactions() -{ - std::vector minersTransactions; - CBlockIndex *pIndexTip = chainActive.LastTip(); - int32_t nHeight = pIndexTip ? pIndexTip->GetHeight() : 0; - - // call here creation of 'miners' transactions... - - // send miner created transaction - CPubKey minerpk = pubkey2pk(Mypubkey()); - for (const auto &tx : minersTransactions) - { - std::string hextx = HexStr(E_MARSHAL(ss << tx)); - UniValue rpcparams(UniValue::VARR), txparam(UniValue::VOBJ); - txparam.setStr(hextx); - rpcparams.push_back(txparam); - try { - // TODO: change sendrawtransaction to low-level RelayTransaction function - sendrawtransaction(rpcparams, false, CPubKey()); // NOTE: throws error, so catch them! - } - catch (std::runtime_error error) - { - LOGSTREAMFN("miner", CCLOG_ERROR, stream << std::string("could not send miner created transaction: bad parameters: ") + error.what()); - } - catch (UniValue error) - { - LOGSTREAMFN("miner", CCLOG_ERROR, stream << std::string("error: could not send miner created tx: ") + error.getValStr()); - } - } - -} diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 3fa2cf209e1..72375e45e80 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1,4 +1,3 @@ - /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -13,14 +12,13 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ -#pragma once // paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse #include "komodo_defs.h" -#include "cc/CCPrices.h" -#include "cc/pricesfeed.h" +#include "komodo_globals.h" +#include "komodo_cJSON.h" -#define KOMODO_MAXPRICES 2048 +int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx); int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base); @@ -34,19 +32,31 @@ struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout void komodo_paxdelete(struct pax_transaction *pax); -void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid, - uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved); // assetchain context +void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved); int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax); -int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights, - int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo); +int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo); int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed); uint64_t komodo_paxtotal(); -static int _paxorder(const void *a,const void *b); +static int _paxorder(const void *a,const void *b) +{ +#define pax_a (*(struct pax_transaction **)a) +#define pax_b (*(struct pax_transaction **)b) + uint64_t aval,bval; + aval = pax_a->fiatoshis + pax_a->komodoshis + pax_a->height; + bval = pax_b->fiatoshis + pax_b->komodoshis + pax_b->height; + if ( bval > aval ) + return(-1); + else if ( bval < aval ) + return(1); + return(0); +#undef pax_a +#undef pax_b +} int32_t komodo_pending_withdraws(char *opretstr); @@ -56,57 +66,63 @@ int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts); int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max); +void komodo_passport_iteration(); + int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); // verify above block is valid pax pricing -/*** - * handle an opreturn - * @param height the height - * @param value the value - * @param opretbuf the buffer - * @param opretlen the length of the buffer - * @param txid - * @param vout - * @param source - * @returns result (i.e. "unknown", "assetchain", "kv", ect. - */ const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source); +int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); + void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_t *filedata,long datalen,char *symbol,char *dest); -/**** - * Load file contents into buffer - * @param fname the filename - * @param bufp the buffer that will contain the file contents - * @param lenp the length of the file - * @param allocsizep the buffer size allocated - * @returns the file contents - */ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -/*** - * Get file contents - * @param allocsizep the size allocated for the file contents (NOTE: this will probably be 64 bytes larger than the file size) - * @param fname the file name - * @returns the data from the file - */ uint8_t *OS_fileptr(long *allocsizep,char *fname); long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest); long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp); -/*** - * Initialize state from the filesystem - * @param sp the state to initialize - * @param fname the filename - * @param symbol - * @param dest - * @returns -1 on error, 1 on success - */ int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest); +uint64_t komodo_interestsum(); + void komodo_passport_iteration(); +extern std::vector Mineropret; // opreturn data set by the data gathering code +#define PRICES_ERRORRATE (COIN / 100) // maximum acceptable change, set at 1% +#define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR +#define KOMODO_LOCALPRICE_CACHESIZE 13 +#define KOMODO_MAXPRICES 2048 +#define PRICES_SMOOTHWIDTH 1 + +#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) + +const char *Cryptos[] = { "KMD", "ETH" }; // must be on binance (for now) +// "LTC", "BCHABC", "XMR", "IOTA", "ZEC", "WAVES", "LSK", "DCR", "RVN", "DASH", "XEM", "BTS", "ICX", "HOT", "STEEM", "ENJ", "STRAT" +const char *Forex[] = +{ "BGN","NZD","ILS","RUB","CAD","PHP","CHF","AUD","JPY","TRY","HKD","MYR","HRK","CZK","IDR","DKK","NOK","HUF","GBP","MXN","THB","ISK","ZAR","BRL","SGD","PLN","INR","KRW","RON","CNY","SEK","EUR" +}; // must be in ECB list + +struct komodo_extremeprice +{ + uint256 blockhash; + uint32_t pricebits,timestamp; + int32_t height; + int16_t dir,ind; +} ExtremePrice; + +struct komodo_priceinfo +{ + FILE *fp; + char symbol[64]; +} PRICES[KOMODO_MAXPRICES]; + +uint32_t PriceCache[KOMODO_LOCALPRICE_CACHESIZE][KOMODO_MAXPRICES];//4+sizeof(Cryptos)/sizeof(*Cryptos)+sizeof(Forex)/sizeof(*Forex)]; +int64_t PriceMult[KOMODO_MAXPRICES]; +int32_t komodo_cbopretsize(uint64_t flags); + void komodo_PriceCache_shift(); int32_t _komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,CBlock *block); @@ -120,27 +136,26 @@ int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHei uint32_t komodo_pricenew(char *maxflagp,uint32_t price,uint32_t refprice,int64_t tolerance); // komodo_pricecmp() returns -1 if any of the prices are beyond the tolerance -int32_t komodo_pricecmp(int32_t nHeight, char *maxflags, uint32_t *pricebitsA, uint32_t *pricebitsB, int32_t begin, int32_t end, int64_t tolerance); +int32_t komodo_pricecmp(int32_t nHeight,int32_t n,char *maxflags,uint32_t *pricebitsA,uint32_t *pricebitsB,int64_t tolerance); // komodo_priceclamp() clamps any price that is beyond tolerance -int32_t komodo_priceclamp(uint32_t *pricebits, uint32_t *refprices, int32_t begin, int32_t end, int64_t tolerance); +int32_t komodo_priceclamp(int32_t n,uint32_t *pricebits,uint32_t *refprices,int64_t tolerance); // komodo_mineropret() returns a valid pricedata to add to the coinbase opreturn for nHeight CScript komodo_mineropret(int32_t nHeight); - -void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits); - /* -validate prices DTO coinbase opreturn with price data + komodo_opretvalidate() is the entire price validation! + it prints out some useful info for debugging, like the lag from current time and prev block and the prices encoded in the opreturn. + + The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data. + + */ -komodo_opretvalidate() is the entire price validation! -it prints out some useful info for debugging, like the lag from current time and prev block and the prices encoded in the opreturn. -The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data. +void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits); -*/ -int32_t komodo_opretvalidate(const CBlock *block, CBlockIndex * const previndex, int32_t nHeight, CScript scriptPubKey); +int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey); char *nonportable_path(char *str); @@ -153,16 +168,39 @@ void *filestr(long *allocsizep,char *_fname); cJSON *send_curl(char *url,char *fname); // get_urljson just returns the JSON returned by the URL using issue_curl + + +/* +const char *Techstocks[] = +{ "AAPL","ADBE","ADSK","AKAM","AMD","AMZN","ATVI","BB","CDW","CRM","CSCO","CYBR","DBX","EA","FB","GDDY","GOOG","GRMN","GSAT","HPQ","IBM","INFY","INTC","INTU","JNPR","MSFT","MSI","MU","MXL","NATI","NCR","NFLX","NTAP","NVDA","ORCL","PANW","PYPL","QCOM","RHT","S","SHOP","SNAP","SPOT","SYMC","SYNA","T","TRIP","TWTR","TXN","VMW","VOD","VRSN","VZ","WDC","XRX","YELP","YNDX","ZEN" +}; +const char *Metals[] = { "XAU", "XAG", "XPT", "XPD", }; + +const char *Markets[] = { "DJIA", "SPX", "NDX", "VIX" }; +*/ + cJSON *get_urljson(char *url); +int32_t get_stockprices(uint32_t now,uint32_t *prices,std::vector symbols); + +uint32_t get_dailyfx(uint32_t *prices); + +uint32_t get_binanceprice(const char *symbol); + +int32_t get_cryptoprices(uint32_t *prices,const char *list[],int32_t n,std::vector strvec); + +// parse the coindesk specific data. yes, if this changes, it will require an update. However, regardless if the format from the data source changes, then the code that extracts it must be changed. One way to mitigate this is to have a large variety of data sources so that there is only a very remote chance that all of them are not available. Certainly the data gathering needs to be made more robust, but it doesnt really affect the proof of concept for the decentralized trustless oracle. The trustlessness is achieved by having all nodes get the oracle data. + +int32_t get_btcusd(uint32_t pricebits[4]); + // komodo_cbopretupdate() obtains the external price data and encodes it into Mineropret, which will then be used by the miner and validation // save history, use new data to approve past rejection, where is the auto-reconsiderblock? + int32_t komodo_cbopretsize(uint64_t flags); void komodo_cbopretupdate(int32_t forceflag); -// get multiplier to normalize prices to 100,000,000 decimal order, to make synthetic indexes -int64_t komodo_pricemult_to10e8(int32_t ind); +int64_t komodo_pricemult(int32_t ind); char *komodo_pricename(char *name,int32_t ind); @@ -184,18 +222,40 @@ void smooth64(int64_t dest[],int64_t src[],int32_t width,int32_t smoothiters); // http://www.holoborodko.com/pavel/numerical-methods/noise-robust-smoothing-filter/ //const int64_t coeffs[7] = { -2, 0, 18, 32, 18, 0, -2 }; -static int cmp_llu(const void *a, const void*b); - -static void sort64(int64_t *l, int32_t llen); - -static int revcmp_llu(const void *a, const void*b); - -static void revsort64(int64_t *l, int32_t llen); +static int cmp_llu(const void *a, const void*b) +{ + if(*(int64_t *)a < *(int64_t *)b) return -1; + else if(*(int64_t *)a > *(int64_t *)b) return 1; + else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism + return(-1); + else return(1); +} + +static void sort64(int64_t *l, int32_t llen) +{ + qsort(l,llen,sizeof(uint64_t),cmp_llu); +} + +static int revcmp_llu(const void *a, const void*b) +{ + if(*(int64_t *)a < *(int64_t *)b) return 1; + else if(*(int64_t *)a > *(int64_t *)b) return -1; + else if ( (uint64_t)a < (uint64_t)b ) // jl777 prevent nondeterminism + return(-1); + else return(1); +} + +static void revsort64(int64_t *l, int32_t llen) +{ + qsort(l,llen,sizeof(uint64_t),revcmp_llu); +} int64_t komodo_priceave(int64_t *buf,int64_t *correlated,int32_t cskip); int32_t komodo_pricesinit(); +pthread_mutex_t pricemutex; + // PRICES file layouts // [0] rawprice32 / timestamp // [1] correlated @@ -205,5 +265,3 @@ int32_t komodo_pricesinit(); void komodo_pricesupdate(int32_t height,CBlock *pblock); int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks); - -void komodo_createminerstransactions(); diff --git a/src/komodo_globals.cpp b/src/komodo_globals.cpp new file mode 100644 index 00000000000..dffafdda929 --- /dev/null +++ b/src/komodo_globals.cpp @@ -0,0 +1,186 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_globals.h" + +int32_t komodo_baseid(char *origbase) +{ + int32_t i; char base[64]; + for (i=0; origbase[i]!=0&&i= 0 && baseid < 32 ) + // cur_money = ASSETCHAINS_GENESISTXVAL + ASSETCHAINS_SUPPLY + nHeight * ASSETCHAINS_REWARD[0] / SATOSHIDEN; + //else + { + // figure out max_money by adding up supply to a maximum of 10,000,000 blocks + cur_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISTXVAL; + if ( ASSETCHAINS_LASTERA == 0 && ASSETCHAINS_REWARD[0] == 0 ) + { + cur_money += (nHeight * 10000);// / SATOSHIDEN; + } + else + { + for ( int j = 0; j <= ASSETCHAINS_LASTERA; j++ ) + { + // if any condition means we have no more rewards, break + if (j != 0 && (nHeight <= ASSETCHAINS_ENDSUBSIDY[j - 1] || (ASSETCHAINS_ENDSUBSIDY[j - 1] == 0 && + (ASSETCHAINS_REWARD[j] == 0 && (j == ASSETCHAINS_LASTERA || ASSETCHAINS_DECAY[j] != SATOSHIDEN))))) + break; + + // add rewards from this era, up to nHeight + int64_t reward = ASSETCHAINS_REWARD[j]; + + //fprintf(stderr,"last.%d reward %llu period %llu\n",(int32_t)ASSETCHAINS_LASTERA,(long long)reward,(long long)ASSETCHAINS_HALVING[j]); + if ( reward > 0 ) + { + uint64_t lastEnd = j == 0 ? 0 : ASSETCHAINS_ENDSUBSIDY[j - 1]; + uint64_t curEnd = ASSETCHAINS_ENDSUBSIDY[j] == 0 ? nHeight : nHeight > ASSETCHAINS_ENDSUBSIDY[j] ? ASSETCHAINS_ENDSUBSIDY[j] : nHeight; + uint64_t period = ASSETCHAINS_HALVING[j]; + if ( period == 0 ) + period = 210000; + uint32_t nSteps = (curEnd - lastEnd) / period; + uint32_t modulo = (curEnd - lastEnd) % period; + uint64_t decay = ASSETCHAINS_DECAY[j]; + + //fprintf(stderr,"period.%llu cur_money %.8f += %.8f * %d\n",(long long)period,(double)cur_money/COIN,(double)reward/COIN,nHeight); + if ( ASSETCHAINS_HALVING[j] == 0 ) + { + // no halving, straight multiply + cur_money += reward * (nHeight - 1); + //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); + } + // if exactly SATOSHIDEN, linear decay to zero or to next era, same as: + // (next_era_reward + (starting reward - next_era_reward) / 2) * num_blocks + else if ( decay == SATOSHIDEN ) + { + int64_t lowestSubsidy, subsidyDifference, stepDifference, stepTriangle; + int64_t denominator, modulo=1; + int32_t sign = 1; + + if ( j == ASSETCHAINS_LASTERA ) + { + subsidyDifference = reward; + lowestSubsidy = 0; + } + else + { + // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 + subsidyDifference = reward - ASSETCHAINS_REWARD[j + 1]; + if (subsidyDifference < 0) + { + sign = -1; + subsidyDifference *= sign; + lowestSubsidy = reward; + } + else + { + lowestSubsidy = ASSETCHAINS_REWARD[j + 1]; + } + } + + // if we have not finished the current era, we need to caluclate a total as if we are at the end, with the current + // subsidy. we will calculate the total of a linear era as follows. Each item represents an area calculation: + // a) the rectangle from 0 to the lowest reward in the era * the number of blocks + // b) the rectangle of the remainder of blocks from the lowest point of the era to the highest point of the era if any remainder + // c) the minor triangle from the start of transition from the lowest point to the start of transition to the highest point + // d) one halving triangle (half area of one full step) + // + // we also need: + // e) number of steps = (n - erastart) / halving interval + // + // the total supply from era start up to height is: + // a + b + c + (d * e) + + // calculate amount in one step's triangular protrusion over minor triangle's hypotenuse + denominator = nSteps * period; + if ( denominator == 0 ) + denominator = 1; + // difference of one step vs. total + stepDifference = (period * subsidyDifference) / denominator; + + // area == coin holding of one step triangle, protruding from minor triangle's hypotenuse + stepTriangle = (period * stepDifference) >> 1; + + // sign is negative if slope is positive (start is less than end) + if (sign < 0) + { + // use steps minus one for our calculations, and add the potentially partial rectangle + // at the end + cur_money += stepTriangle * (nSteps - 1); + cur_money += stepTriangle * (nSteps - 1) * (nSteps - 1); + + // difference times number of steps is height of rectangle above lowest subsidy + cur_money += modulo * stepDifference * nSteps; + } + else + { + // if negative slope, the minor triangle is the full number of steps, as the highest + // level step is full. lowest subsidy is just the lowest so far + lowestSubsidy = reward - (stepDifference * nSteps); + + // add the step triangles, one per step + cur_money += stepTriangle * nSteps; + + // add the minor triangle + cur_money += stepTriangle * nSteps * nSteps; + } + + // add more for the base rectangle if lowest subsidy is not 0 + cur_money += lowestSubsidy * (curEnd - lastEnd); + } + else + { + for ( int k = lastEnd; k < curEnd; k += period ) + { + cur_money += period * reward; + // if zero, we do straight halving + reward = decay ? (reward * decay) / SATOSHIDEN : reward >> 1; + } + cur_money += modulo * reward; + } + } + } + } + } + if ( KOMODO_BIT63SET(cur_money) != 0 ) + return(KOMODO_MAXNVALUE); + if ( ASSETCHAINS_COMMISSION != 0 ) + { + uint64_t newval = (cur_money + (cur_money/COIN * ASSETCHAINS_COMMISSION)); + if ( KOMODO_BIT63SET(newval) != 0 ) + return(KOMODO_MAXNVALUE); + else if ( newval < cur_money ) // check for underflow + return(KOMODO_MAXNVALUE); + return(newval); + } + //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); + return(cur_money); +} diff --git a/src/komodo_globals.h b/src/komodo_globals.h index e4445947a24..d244c425ded 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -15,6 +15,7 @@ #pragma once #include #include "komodo_defs.h" +#include "komodo_structs.h" void komodo_prefetch(FILE *fp); uint32_t komodo_heightstamp(int32_t height); @@ -138,172 +139,6 @@ char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", "KMD" }; -int32_t komodo_baseid(char *origbase) -{ - int32_t i; char base[64]; - for (i=0; origbase[i]!=0&&i= 0 && baseid < 32 ) - // cur_money = ASSETCHAINS_GENESISTXVAL + ASSETCHAINS_SUPPLY + nHeight * ASSETCHAINS_REWARD[0] / SATOSHIDEN; - //else - { - // figure out max_money by adding up supply to a maximum of 10,000,000 blocks - cur_money = (ASSETCHAINS_SUPPLY+1) * SATOSHIDEN + (ASSETCHAINS_MAGIC & 0xffffff) + ASSETCHAINS_GENESISTXVAL; - if ( ASSETCHAINS_LASTERA == 0 && ASSETCHAINS_REWARD[0] == 0 ) - { - cur_money += (nHeight * 10000);// / SATOSHIDEN; - } - else - { - for ( int j = 0; j <= ASSETCHAINS_LASTERA; j++ ) - { - // if any condition means we have no more rewards, break - if (j != 0 && (nHeight <= ASSETCHAINS_ENDSUBSIDY[j - 1] || (ASSETCHAINS_ENDSUBSIDY[j - 1] == 0 && - (ASSETCHAINS_REWARD[j] == 0 && (j == ASSETCHAINS_LASTERA || ASSETCHAINS_DECAY[j] != SATOSHIDEN))))) - break; - - // add rewards from this era, up to nHeight - int64_t reward = ASSETCHAINS_REWARD[j]; - - //fprintf(stderr,"last.%d reward %llu period %llu\n",(int32_t)ASSETCHAINS_LASTERA,(long long)reward,(long long)ASSETCHAINS_HALVING[j]); - if ( reward > 0 ) - { - uint64_t lastEnd = j == 0 ? 0 : ASSETCHAINS_ENDSUBSIDY[j - 1]; - uint64_t curEnd = ASSETCHAINS_ENDSUBSIDY[j] == 0 ? nHeight : nHeight > ASSETCHAINS_ENDSUBSIDY[j] ? ASSETCHAINS_ENDSUBSIDY[j] : nHeight; - uint64_t period = ASSETCHAINS_HALVING[j]; - if ( period == 0 ) - period = 210000; - uint32_t nSteps = (curEnd - lastEnd) / period; - uint32_t modulo = (curEnd - lastEnd) % period; - uint64_t decay = ASSETCHAINS_DECAY[j]; - - //fprintf(stderr,"period.%llu cur_money %.8f += %.8f * %d\n",(long long)period,(double)cur_money/COIN,(double)reward/COIN,nHeight); - if ( ASSETCHAINS_HALVING[j] == 0 ) - { - // no halving, straight multiply - cur_money += reward * (nHeight - 1); - //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); - } - // if exactly SATOSHIDEN, linear decay to zero or to next era, same as: - // (next_era_reward + (starting reward - next_era_reward) / 2) * num_blocks - else if ( decay == SATOSHIDEN ) - { - int64_t lowestSubsidy, subsidyDifference, stepDifference, stepTriangle; - int64_t denominator, modulo=1; - int32_t sign = 1; - - if ( j == ASSETCHAINS_LASTERA ) - { - subsidyDifference = reward; - lowestSubsidy = 0; - } - else - { - // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 - subsidyDifference = reward - ASSETCHAINS_REWARD[j + 1]; - if (subsidyDifference < 0) - { - sign = -1; - subsidyDifference *= sign; - lowestSubsidy = reward; - } - else - { - lowestSubsidy = ASSETCHAINS_REWARD[j + 1]; - } - } - - // if we have not finished the current era, we need to caluclate a total as if we are at the end, with the current - // subsidy. we will calculate the total of a linear era as follows. Each item represents an area calculation: - // a) the rectangle from 0 to the lowest reward in the era * the number of blocks - // b) the rectangle of the remainder of blocks from the lowest point of the era to the highest point of the era if any remainder - // c) the minor triangle from the start of transition from the lowest point to the start of transition to the highest point - // d) one halving triangle (half area of one full step) - // - // we also need: - // e) number of steps = (n - erastart) / halving interval - // - // the total supply from era start up to height is: - // a + b + c + (d * e) - - // calculate amount in one step's triangular protrusion over minor triangle's hypotenuse - denominator = nSteps * period; - if ( denominator == 0 ) - denominator = 1; - // difference of one step vs. total - stepDifference = (period * subsidyDifference) / denominator; - - // area == coin holding of one step triangle, protruding from minor triangle's hypotenuse - stepTriangle = (period * stepDifference) >> 1; - - // sign is negative if slope is positive (start is less than end) - if (sign < 0) - { - // use steps minus one for our calculations, and add the potentially partial rectangle - // at the end - cur_money += stepTriangle * (nSteps - 1); - cur_money += stepTriangle * (nSteps - 1) * (nSteps - 1); - - // difference times number of steps is height of rectangle above lowest subsidy - cur_money += modulo * stepDifference * nSteps; - } - else - { - // if negative slope, the minor triangle is the full number of steps, as the highest - // level step is full. lowest subsidy is just the lowest so far - lowestSubsidy = reward - (stepDifference * nSteps); - - // add the step triangles, one per step - cur_money += stepTriangle * nSteps; - - // add the minor triangle - cur_money += stepTriangle * nSteps * nSteps; - } - - // add more for the base rectangle if lowest subsidy is not 0 - cur_money += lowestSubsidy * (curEnd - lastEnd); - } - else - { - for ( int k = lastEnd; k < curEnd; k += period ) - { - cur_money += period * reward; - // if zero, we do straight halving - reward = decay ? (reward * decay) / SATOSHIDEN : reward >> 1; - } - cur_money += modulo * reward; - } - } - } - } - } - if ( KOMODO_BIT63SET(cur_money) != 0 ) - return(KOMODO_MAXNVALUE); - if ( ASSETCHAINS_COMMISSION != 0 ) - { - uint64_t newval = (cur_money + (cur_money/COIN * ASSETCHAINS_COMMISSION)); - if ( KOMODO_BIT63SET(newval) != 0 ) - return(KOMODO_MAXNVALUE); - else if ( newval < cur_money ) // check for underflow - return(KOMODO_MAXNVALUE); - return(newval); - } - //fprintf(stderr,"cur_money %.8f\n",(double)cur_money/COIN); - return(cur_money); -} +uint64_t komodo_current_supply(uint32_t nHeight); diff --git a/src/komodo_interest.cpp b/src/komodo_interest.cpp new file mode 100644 index 00000000000..b862272132b --- /dev/null +++ b/src/komodo_interest.cpp @@ -0,0 +1,137 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_interest.h" + +uint64_t _komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +{ + int32_t minutes; uint64_t interest = 0; + if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= (KOMODO_MAXMEMPOOLTIME/60) ) + { + if ( minutes > 365 * 24 * 60 ) + minutes = 365 * 24 * 60; + if ( txheight >= 1000000 && minutes > 31 * 24 * 60 ) + minutes = 31 * 24 * 60; + minutes -= ((KOMODO_MAXMEMPOOLTIME/60) - 1); + interest = ((nValue / 10512000) * minutes); + } + return(interest); +} + +uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +{ + uint64_t interest = 0; + if ( txheight < KOMODO_ENDOFERA && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && + interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + return(interest); +} + +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) +{ + int32_t minutes,exception; uint64_t interestnew,numerator,denominator,interest = 0; uint32_t activation; + activation = 1491350400; // 1491350400 5th April + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + return(0); + if ( txheight >= KOMODO_ENDOFERA ) + return(0); + if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && + { + if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) + { + if ( minutes > 365 * 24 * 60 ) + minutes = 365 * 24 * 60; + if ( txheight >= 250000 ) + minutes -= 59; + denominator = (((uint64_t)365 * 24 * 60) / minutes); + if ( denominator == 0 ) + denominator = 1; // max KOMODO_INTEREST per transfer, do it at least annually! + if ( nValue > 25000LL*COIN ) + { + exception = 0; + if ( txheight <= 155949 ) + { + if ( (txheight == 116607 && nValue == 2502721100000LL) || + (txheight == 126891 && nValue == 2879650000000LL) || + (txheight == 129510 && nValue == 3000000000000LL) || + (txheight == 141549 && nValue == 3500000000000LL) || + (txheight == 154473 && nValue == 3983399350000LL) || + (txheight == 154736 && nValue == 3983406748175LL) || + (txheight == 155013 && nValue == 3983414006565LL) || + (txheight == 155492 && nValue == 3983427592291LL) || + (txheight == 155613 && nValue == 9997409999999797LL) || + (txheight == 157927 && nValue == 9997410667451072LL) || + (txheight == 155613 && nValue == 2590000000000LL) || + (txheight == 155949 && nValue == 4000000000000LL) ) + exception = 1; + if ( exception == 0 || nValue == 4000000000000LL ) + printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); + } + //if ( nValue == 4000000000000LL ) + // printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); + if ( exception == 0 ) + { + numerator = (nValue / 20); // assumes 5%! + if ( txheight < 250000 ) + interest = (numerator / denominator); + else if ( txheight < 1000000 ) + { + interest = (numerator * minutes) / ((uint64_t)365 * 24 * 60); + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + if ( interest < interestnew ) + printf("pathA current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); + } + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + } + else if ( txheight < 1000000 ) + { + numerator = (nValue * KOMODO_INTEREST); + interest = (numerator / denominator) / COIN; + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + if ( interest < interestnew ) + printf("pathB current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); + } + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + } + else + { + /* 250000 algo + numerator = (nValue * KOMODO_INTEREST); + if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) + interest = (numerator / denominator) / COIN; + else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; + */ + numerator = (nValue * KOMODO_INTEREST); + if ( txheight < 250000 || tiptime < activation ) + { + if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) + interest = (numerator / denominator) / COIN; + else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; + } + else if ( txheight < 1000000 ) + { + numerator = (nValue / 20); // assumes 5%! + interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)); + //fprintf(stderr,"interest %llu %.8f <- numerator.%llu minutes.%d\n",(long long)interest,(double)interest/COIN,(long long)numerator,(int32_t)minutes); + interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + if ( interest < interestnew ) + fprintf(stderr,"pathC current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); + } + else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); + } + if ( 0 && numerator == (nValue * KOMODO_INTEREST) ) + fprintf(stderr,"komodo_interest.%d %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu) prod.%llu\n",txheight,(long long)nValue,(double)nValue/COIN,nLockTime,tiptime,minutes,(long long)interest,(double)interest/COIN,(long long)numerator,(long long)denominator,(long long)(numerator * minutes)); + } + } + return(interest); +} diff --git a/src/komodo_interest.h b/src/komodo_interest.h index b9549d8609e..d8c7ed7859d 100644 --- a/src/komodo_interest.h +++ b/src/komodo_interest.h @@ -23,182 +23,8 @@ extern int64_t MAX_MONEY; extern uint8_t NOTARY_PUBKEY33[]; -#ifdef notanymore -uint64_t komodo_earned_interest(int32_t height,int64_t paidinterest) -{ - static uint64_t *interests; static int32_t maxheight; - uint64_t total; int32_t ind,incr = 10000; - // need to make interests persistent before 2030, or just hardfork interest/mining rewards disable after MAX_MONEY is exceeded - return(0); - if ( height >= maxheight ) - { - if ( interests == 0 ) - { - maxheight = height + incr; - interests = (uint64_t *)calloc(maxheight,sizeof(*interests) * 2); - } - else - { - interests = (uint64_t *)realloc(interests,(maxheight + incr) * sizeof(*interests) * 2); - memset(&interests[maxheight << 1],0,incr * sizeof(*interests) * 2); - maxheight += incr; - } - } - ind = (height << 1); - if ( paidinterest < 0 ) // request - { - return(interests[ind]); - } - else - { - if ( interests[ind + 1] != paidinterest ) // need to handle skips like at 80000 - { - //fprintf(stderr,"interests.%d %.8f %.8f vs paidinterest %.8f\n",height,dstr(interests[ind]),dstr(interests[ind+1]),dstr(paidinterest)); - interests[ind + 1] = paidinterest; - if ( height <= 1 ) - interests[ind] = 0; - else interests[ind] = interests[ind - 2] + interests[ind - 1]; - total = interests[ind] + paidinterest; - //fprintf(stderr,"reset interests[height.%d to maxheight.%d] <- %.8f\n",height,maxheight,dstr(total)); - for (++height; height= LOCKTIME_THRESHOLD && tiptime > nLockTime && (minutes= (tiptime - nLockTime) / 60) >= (KOMODO_MAXMEMPOOLTIME/60) ) - { - if ( minutes > 365 * 24 * 60 ) - minutes = 365 * 24 * 60; - if ( txheight >= 1000000 && minutes > 31 * 24 * 60 ) - minutes = 31 * 24 * 60; - minutes -= ((KOMODO_MAXMEMPOOLTIME/60) - 1); - interest = ((nValue / 10512000) * minutes); - } - return(interest); -} - -uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) -{ - uint64_t interest = 0; - if ( txheight < KOMODO_ENDOFERA && nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && - interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - return(interest); -} - -uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime) -{ - int32_t minutes,exception; uint64_t interestnew,numerator,denominator,interest = 0; uint32_t activation; - activation = 1491350400; // 1491350400 5th April - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - return(0); - if ( txheight >= KOMODO_ENDOFERA ) - return(0); - if ( nLockTime >= LOCKTIME_THRESHOLD && tiptime != 0 && nLockTime < tiptime && nValue >= 10*COIN ) //komodo_moneysupply(txheight) < MAX_MONEY && - { - if ( (minutes= (tiptime - nLockTime) / 60) >= 60 ) - { - if ( minutes > 365 * 24 * 60 ) - minutes = 365 * 24 * 60; - if ( txheight >= 250000 ) - minutes -= 59; - denominator = (((uint64_t)365 * 24 * 60) / minutes); - if ( denominator == 0 ) - denominator = 1; // max KOMODO_INTEREST per transfer, do it at least annually! - if ( nValue > 25000LL*COIN ) - { - exception = 0; - if ( txheight <= 155949 ) - { - if ( (txheight == 116607 && nValue == 2502721100000LL) || - (txheight == 126891 && nValue == 2879650000000LL) || - (txheight == 129510 && nValue == 3000000000000LL) || - (txheight == 141549 && nValue == 3500000000000LL) || - (txheight == 154473 && nValue == 3983399350000LL) || - (txheight == 154736 && nValue == 3983406748175LL) || - (txheight == 155013 && nValue == 3983414006565LL) || - (txheight == 155492 && nValue == 3983427592291LL) || - (txheight == 155613 && nValue == 9997409999999797LL) || - (txheight == 157927 && nValue == 9997410667451072LL) || - (txheight == 155613 && nValue == 2590000000000LL) || - (txheight == 155949 && nValue == 4000000000000LL) ) - exception = 1; - if ( exception == 0 || nValue == 4000000000000LL ) - printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); - } - //if ( nValue == 4000000000000LL ) - // printf(">>>>>>>>>>>> exception.%d txheight.%d %.8f locktime %u vs tiptime %u <<<<<<<<<\n",exception,txheight,(double)nValue/COIN,nLockTime,tiptime); - if ( exception == 0 ) - { - numerator = (nValue / 20); // assumes 5%! - if ( txheight < 250000 ) - interest = (numerator / denominator); - else if ( txheight < 1000000 ) - { - interest = (numerator * minutes) / ((uint64_t)365 * 24 * 60); - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - if ( interest < interestnew ) - printf("pathA current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); - } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - } - else if ( txheight < 1000000 ) - { - numerator = (nValue * KOMODO_INTEREST); - interest = (numerator / denominator) / COIN; - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - if ( interest < interestnew ) - printf("pathB current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); - } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - } - else - { - /* 250000 algo - numerator = (nValue * KOMODO_INTEREST); - if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) - interest = (numerator / denominator) / COIN; - else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; - */ - numerator = (nValue * KOMODO_INTEREST); - if ( txheight < 250000 || tiptime < activation ) - { - if ( txheight < 250000 || numerator * minutes < 365 * 24 * 60 ) - interest = (numerator / denominator) / COIN; - else interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)) / COIN; - } - else if ( txheight < 1000000 ) - { - numerator = (nValue / 20); // assumes 5%! - interest = ((numerator * minutes) / ((uint64_t)365 * 24 * 60)); - //fprintf(stderr,"interest %llu %.8f <- numerator.%llu minutes.%d\n",(long long)interest,(double)interest/COIN,(long long)numerator,(int32_t)minutes); - interestnew = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - if ( interest < interestnew ) - fprintf(stderr,"pathC current interest %.8f vs new %.8f for ht.%d %.8f locktime.%u tiptime.%u\n",dstr(interest),dstr(interestnew),txheight,dstr(nValue),nLockTime,tiptime); - } - else interest = _komodo_interestnew(txheight,nValue,nLockTime,tiptime); - } - if ( 0 && numerator == (nValue * KOMODO_INTEREST) ) - fprintf(stderr,"komodo_interest.%d %lld %.8f nLockTime.%u tiptime.%u minutes.%d interest %lld %.8f (%llu / %llu) prod.%llu\n",txheight,(long long)nValue,(double)nValue/COIN,nLockTime,tiptime,minutes,(long long)interest,(double)interest/COIN,(long long)numerator,(long long)denominator,(long long)(numerator * minutes)); - } - } - return(interest); -} +uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); diff --git a/src/komodo_jumblr.cpp b/src/komodo_jumblr.cpp new file mode 100644 index 00000000000..92dbcdda2f3 --- /dev/null +++ b/src/komodo_jumblr.cpp @@ -0,0 +1,756 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_jumblr.h" +#include "komodo_bitcoind.h" // komodo_issuemethod + +char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) +{ + cJSON *retjson,*resjson = 0; char *retstr; + if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,(char *)"result") != 0 ) + resjson = jduplicate(jobj(retjson,(char *)"result")); + else if ( jobj(retjson,(char *)"error") != 0 ) + resjson = jduplicate(jobj(retjson,(char *)"error")); + else + { + resjson = cJSON_CreateObject(); + jaddstr(resjson,(char *)"error",(char *)"cant parse return"); + } + free_json(retjson); + } + free(retstr); + } + if ( resjson != 0 ) + return(jprint(resjson,1)); + else return(clonestr((char *)"{\"error\":\"unknown error\"}")); +} + +char *jumblr_importaddress(char *address) +{ + char params[1024]; + sprintf(params,"[\"%s\", \"%s\", false]",address,address); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_validateaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\"]",addr); + printf("validateaddress.%s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); +} + +int32_t Jumblr_secretaddrfind(char *searchaddr) +{ + int32_t i; + for (i=0; i 0 ) + { + OS_randombytes((uint8_t *)&r,sizeof(r)); + r %= Jumblr_numsecretaddrs; + safecopy(secretaddr,Jumblr_secretaddrs[r],64); + } + return(r); +} + +int32_t jumblr_addresstype(char *addr) +{ + if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) + { + addr[strlen(addr)-1] = 0; + addr++; + } + if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) + return('z'); + else if ( strlen(addr) < 40 ) + return('t'); + printf("strange.(%s)\n",addr); + return(-1); +} + +struct jumblr_item *jumblr_opidfind(char *opid) +{ + struct jumblr_item *ptr; + HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); + return(ptr); +} + +struct jumblr_item *jumblr_opidadd(char *opid) +{ + struct jumblr_item *ptr = 0; + if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) + { + ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); + safecopy(ptr->opid,opid,sizeof(ptr->opid)); + HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); + if ( ptr != jumblr_opidfind(opid) ) + printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); + } + return(ptr); +} + +char *jumblr_zgetnewaddress() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistoperationids() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetoperationresult(char *opid) +{ + char params[1024]; + sprintf(params,"[[\"%s\"]]",opid); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetoperationstatus(char *opid) +{ + char params[1024]; + sprintf(params,"[[\"%s\"]]",opid); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) +{ + char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; + if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) + return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + printf("t -> z: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) +{ + char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; + if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) + return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); + //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); + printf("z -> z: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) +{ + char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; + if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) + return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + printf("z -> t: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistaddresses() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistreceivedbyaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_getreceivedbyaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_importprivkey(char *wifstr) +{ + char params[1024]; + sprintf(params,"[\"%s\", \"\", false]",wifstr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetbalance(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); +} + +char *jumblr_listunspent(char *coinaddr) +{ + char params[1024]; + sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); +} + +char *jumblr_gettransaction(char *txidstr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",txidstr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); +} + +int32_t jumblr_numvins(bits256 txid) +{ + char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; + bits256_str(txidstr,txid); + if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) + { + numvins = n; + //printf("numvins.%d\n",n); + } //else printf("no vin.(%s)\n",retstr); + free_json(retjson); + } + free(retstr); + } + return(numvins); +} + +int64_t jumblr_receivedby(char *addr) +{ + char *retstr; int64_t total = 0; + if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) + { + total = atof(retstr) * SATOSHIDEN; + free(retstr); + } + return(total); +} + +int64_t jumblr_balance(char *addr) +{ + char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; + /*if ( jumblr_addresstype(addr) == 't' ) + { + if ( (retstr= jumblr_listunspent(addr)) != 0 ) + { + //printf("jumblr.[%s].(%s)\n","KMD",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) + for (i=0; i SMALLVAL ) + balance = val * SATOSHIDEN; + free(retstr); + } + return(balance); +} + +int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) +{ + cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; + /*"params" : { + "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", + "amounts" : [ + { + "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", + "amount" : 3.00000000 + } + ], + "minconf" : 1, + "fee" : 0.00010000 + }*/ + if ( (params= jobj(item,(char *)"params")) != 0 ) + { + //printf("params.(%s)\n",jprint(params,0)); + if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) + { + safecopy(ptr->src,from,sizeof(ptr->src)); + } + if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) + { + for (i=0; i 0 ) + { + if ( strcmp(addr,JUMBLR_ADDR) == 0 ) + ptr->fee = amount; + else + { + ptr->amount = amount; + safecopy(ptr->dest,addr,sizeof(ptr->dest)); + } + } + } + } + ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; + } + return(1); +} + +void jumblr_opidupdate(struct jumblr_item *ptr) +{ + char *retstr,*status; cJSON *retjson,*item; + if ( ptr->status == 0 ) + { + if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) + { + item = jitem(retjson,0); + //printf("%s\n",jprint(item,0)); + if ( (status= jstr(item,(char *)"status")) != 0 ) + { + if ( strcmp(status,(char *)"success") == 0 ) + { + ptr->status = jumblr_itemset(ptr,item,status); + if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) + { + printf("a non-jumblr t->z pruned\n"); + free(jumblr_zgetoperationresult(ptr->opid)); + ptr->status = -1; + } + + } + else if ( strcmp(status,(char *)"failed") == 0 ) + { + printf("jumblr_opidupdate %s failed\n",ptr->opid); + free(jumblr_zgetoperationresult(ptr->opid)); + ptr->status = -1; + } + } + } + free_json(retjson); + } + free(retstr); + } + } +} + +void jumblr_prune(struct jumblr_item *ptr) +{ + struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; + if ( is_hexstr(ptr->opid,0) == 64 ) + return; + printf("jumblr_prune %s\n",ptr->opid); + strcpy(oldsrc,ptr->src); + free(jumblr_zgetoperationresult(ptr->opid)); + while ( flag != 0 ) + { + flag = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + if ( strcmp(oldsrc,ptr->dest) == 0 ) + { + if ( is_hexstr(ptr->opid,0) != 64 ) + { + printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); + free(jumblr_zgetoperationresult(ptr->opid)); + strcpy(oldsrc,ptr->src); + flag = 1; + break; + } + } + } + } +} + + +bits256 jbits256(cJSON *json,char *field); + + +void jumblr_zaddrinit(char *zaddr) +{ + struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; + if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) + { + if ( (total= atof(totalstr)) > SMALLVAL ) + { + if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + t_z = z_z = 0; + if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) + { + item = jitem(array,0); + if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) + { + txid = jbits256(item,(char *)"txid"); + bits256_str(txidstr,txid); + if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) + { + ptr->amount = (total * SATOSHIDEN); + ptr->status = 1; + strcpy(ptr->dest,zaddr); + if ( jumblr_addresstype(ptr->dest) != 'z' ) + printf("error setting dest type to Z: %s\n",jprint(item,0)); + if ( jumblr_numvins(txid) == 0 ) + { + z_z = 1; + strcpy(ptr->src,zaddr); + ptr->src[3] = '0'; + ptr->src[4] = '0'; + ptr->src[5] = '0'; + if ( jumblr_addresstype(ptr->src) != 'z' ) + printf("error setting address type to Z: %s\n",jprint(item,0)); + } + else + { + t_z = 1; + strcpy(ptr->src,"taddr"); + if ( jumblr_addresstype(ptr->src) != 't' ) + printf("error setting address type to T: %s\n",jprint(item,0)); + } + printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend + } + } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); + } + free_json(array); + } + free(retstr); + } + } + free(totalstr); + } +} + +void jumblr_opidsupdate() +{ + char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; + if ( (retstr= jumblr_zlistoperationids()) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) + { + //printf("%s -> n%d\n",retstr,n); + for (i=0; istatus == 0 ) + jumblr_opidupdate(ptr); + //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); + if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) + jumblr_prune(ptr); + } + } + } + free_json(array); + } + free(retstr); + } +} + +uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) +{ + int32_t i,n; uint64_t incrs[1000],remains = total; + height /= JUMBLR_SYNCHRONIZED_BLOCKS; + if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) + { + if ( total >= biggest ) + return(biggest); + else if ( total >= medium ) + return(medium); + else if ( total >= smallest ) + return(smallest); + else return(0); + } + else + { + n = 0; + while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) + { + if ( remains >= biggest ) + incrs[n] = biggest; + else if ( remains >= medium ) + incrs[n] = medium; + else if ( remains >= smallest ) + incrs[n] = smallest; + else break; + remains -= incrs[n]; + n++; + } + if ( n > 0 ) + { + r %= n; + for (i=0; i %.8f\n",n,r,dstr(incrs[r])); + return(incrs[r]); + } + } + return(0); +} + +void jumblr_iteration() +{ + static int32_t lastheight; static uint32_t lasttime; + char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; + acpublic = ASSETCHAINS_PUBLIC; + if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) + acpublic = 1; + if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) + return; + if ( lasttime == 0 ) + { + if ( (retstr= jumblr_zlistaddresses()) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) + { + for (i=0; iGetHeight(); + if ( time(NULL) < lasttime+40 ) + return; + lasttime = (uint32_t)time(NULL); + if ( lastheight == height ) + return; + lastheight = height; + if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) + return; + fee = JUMBLR_INCR * JUMBLR_FEE; + smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); + medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); + biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); + OS_randombytes((uint8_t *)&r,sizeof(r)); + s = (r % 3); + //printf("jumblr_iteration r.%u s.%u\n",r,s); + switch ( s ) + { + case 0: // t -> z + default: + if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) + { + if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) + { + if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) + { + zaddr[strlen(zaddr)-1] = 0; + addr = zaddr+1; + } else addr = zaddr; + amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); + /* + amount = 0; + if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) + amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); + else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) + amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); + else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ + if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) + { + printf("sendt_to_z.(%s)\n",retstr); + free(retstr), retstr = 0; + } + free(zaddr); + } else printf("no zaddr from jumblr_zgetnewaddress\n"); + } + else if ( Jumblr_deposit[0] != 0 ) + printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); + break; + case 1: // z -> z + jumblr_opidsupdate(); + chosen_one = -1; + for (iter=counter=0; iter<2; iter++) + { + counter = n = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) + { + if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + { + if ( iter == 1 && counter == chosen_one ) + { + if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) + { + if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) + { + zaddr[strlen(zaddr)-1] = 0; + addr = zaddr+1; + } else addr = zaddr; + if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) + { + printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); + free(retstr), retstr = 0; + } + ptr->spent = (uint32_t)time(NULL); + free(zaddr); + break; + } + } + counter++; + } + } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); + } + } + break; + case 2: // z -> t + if ( Jumblr_numsecretaddrs > 0 ) + { + jumblr_opidsupdate(); + chosen_one = -1; + for (iter=0; iter<2; iter++) + { + counter = n = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); + if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) + { + if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + { + if ( iter == 1 && counter == chosen_one ) + { + Jumblr_secretaddr(secretaddr); + if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) + { + printf("%s send z_to_t.(%s)\n",secretaddr,retstr); + free(retstr), retstr = 0; + } else printf("null return from jumblr_sendz_to_t\n"); + ptr->spent = (uint32_t)time(NULL); + break; + } + counter++; + } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); + } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); + } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); + } + } + break; + } +} diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h index fca7395e5d3..9d28c567041 100644 --- a/src/komodo_jumblr.h +++ b/src/komodo_jumblr.h @@ -12,17 +12,9 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -/* - z_exportkey "zaddr" - z_exportwallet "filename" - z_getoperationstatus (["operationid", ... ]) - z_gettotalbalance ( minconf ) - z_importkey "zkey" ( rescan ) - z_importwallet "filename" - z_listaddresses - z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":""},...] ( minconf ) ( fee ) - */ +#pragma once +#include "uthash.h" // UT_hash_handle +#include "komodo_cJSON.h" #ifdef _WIN32 #include @@ -54,742 +46,70 @@ struct jumblr_item char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64]; int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode -char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) -{ - cJSON *retjson,*resjson = 0; char *retstr; - if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"result") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"result")); - else if ( jobj(retjson,(char *)"error") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"error")); - else - { - resjson = cJSON_CreateObject(); - jaddstr(resjson,(char *)"error",(char *)"cant parse return"); - } - free_json(retjson); - } - free(retstr); - } - if ( resjson != 0 ) - return(jprint(resjson,1)); - else return(clonestr((char *)"{\"error\":\"unknown error\"}")); -} - -char *jumblr_importaddress(char *address) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"%s\", false]",address,address); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port); -char *jumblr_validateaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\"]",addr); - printf("validateaddress.%s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_importaddress(char *address); -int32_t Jumblr_secretaddrfind(char *searchaddr) -{ - int32_t i; - for (i=0; i 0 ) - { - OS_randombytes((uint8_t *)&r,sizeof(r)); - r %= Jumblr_numsecretaddrs; - safecopy(secretaddr,Jumblr_secretaddrs[r],64); - } - return(r); -} - -int32_t jumblr_addresstype(char *addr) -{ - if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) - { - addr[strlen(addr)-1] = 0; - addr++; - } - if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) - return('z'); - else if ( strlen(addr) < 40 ) - return('t'); - printf("strange.(%s)\n",addr); - return(-1); -} - -struct jumblr_item *jumblr_opidfind(char *opid) -{ - struct jumblr_item *ptr; - HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); - return(ptr); -} +int32_t Jumblr_secretaddradd(char *secretaddr); // external -struct jumblr_item *jumblr_opidadd(char *opid) -{ - struct jumblr_item *ptr = 0; - if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) - { - ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); - safecopy(ptr->opid,opid,sizeof(ptr->opid)); - HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); - if ( ptr != jumblr_opidfind(opid) ) - printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); - } - return(ptr); -} - -char *jumblr_zgetnewaddress() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); -} +int32_t Jumblr_depositaddradd(char *depositaddr); // external -char *jumblr_zlistoperationids() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); -} +int32_t Jumblr_secretaddr(char *secretaddr); -char *jumblr_zgetoperationresult(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); -} +int32_t jumblr_addresstype(char *addr); -char *jumblr_zgetoperationstatus(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); -} +struct jumblr_item *jumblr_opidfind(char *opid); -char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) -{ - char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("t -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) -{ - char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; - if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); - //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); - printf("z -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) -{ - char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("z -> t: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistaddresses() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); -} +struct jumblr_item *jumblr_opidadd(char *opid); -char *jumblr_zlistreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_zgetnewaddress(); -char *jumblr_getreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); -} +char *jumblr_zlistoperationids(); -char *jumblr_importprivkey(char *wifstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"\", false]",wifstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); -} +char *jumblr_zgetoperationresult(char *opid); -char *jumblr_zgetbalance(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); -} +char *jumblr_zgetoperationstatus(char *opid); -char *jumblr_listunspent(char *coinaddr) -{ - char params[1024]; - sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); -} +char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount); -char *jumblr_gettransaction(char *txidstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",txidstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); -} +char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount); -int32_t jumblr_numvins(bits256 txid) -{ - char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; - bits256_str(txidstr,txid); - if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) - { - numvins = n; - //printf("numvins.%d\n",n); - } //else printf("no vin.(%s)\n",retstr); - free_json(retjson); - } - free(retstr); - } - return(numvins); -} - -int64_t jumblr_receivedby(char *addr) -{ - char *retstr; int64_t total = 0; - if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) - { - total = atof(retstr) * SATOSHIDEN; - free(retstr); - } - return(total); -} - -int64_t jumblr_balance(char *addr) -{ - char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; - /*if ( jumblr_addresstype(addr) == 't' ) - { - if ( (retstr= jumblr_listunspent(addr)) != 0 ) - { - //printf("jumblr.[%s].(%s)\n","KMD",retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) - for (i=0; i SMALLVAL ) - balance = val * SATOSHIDEN; - free(retstr); - } - return(balance); -} - -int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) -{ - cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; - /*"params" : { - "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", - "amounts" : [ - { - "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", - "amount" : 3.00000000 - } - ], - "minconf" : 1, - "fee" : 0.00010000 - }*/ - if ( (params= jobj(item,(char *)"params")) != 0 ) - { - //printf("params.(%s)\n",jprint(params,0)); - if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) - { - safecopy(ptr->src,from,sizeof(ptr->src)); - } - if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) - { - for (i=0; i 0 ) - { - if ( strcmp(addr,JUMBLR_ADDR) == 0 ) - ptr->fee = amount; - else - { - ptr->amount = amount; - safecopy(ptr->dest,addr,sizeof(ptr->dest)); - } - } - } - } - ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; - } - return(1); -} - -void jumblr_opidupdate(struct jumblr_item *ptr) -{ - char *retstr,*status; cJSON *retjson,*item; - if ( ptr->status == 0 ) - { - if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) - { - item = jitem(retjson,0); - //printf("%s\n",jprint(item,0)); - if ( (status= jstr(item,(char *)"status")) != 0 ) - { - if ( strcmp(status,(char *)"success") == 0 ) - { - ptr->status = jumblr_itemset(ptr,item,status); - if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) - { - printf("a non-jumblr t->z pruned\n"); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - - } - else if ( strcmp(status,(char *)"failed") == 0 ) - { - printf("jumblr_opidupdate %s failed\n",ptr->opid); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - } - } - free_json(retjson); - } - free(retstr); - } - } -} - -void jumblr_prune(struct jumblr_item *ptr) -{ - struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; - if ( is_hexstr(ptr->opid,0) == 64 ) - return; - printf("jumblr_prune %s\n",ptr->opid); - strcpy(oldsrc,ptr->src); - free(jumblr_zgetoperationresult(ptr->opid)); - while ( flag != 0 ) - { - flag = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( strcmp(oldsrc,ptr->dest) == 0 ) - { - if ( is_hexstr(ptr->opid,0) != 64 ) - { - printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); - free(jumblr_zgetoperationresult(ptr->opid)); - strcpy(oldsrc,ptr->src); - flag = 1; - break; - } - } - } - } -} - - -bits256 jbits256(cJSON *json,char *field); - - -void jumblr_zaddrinit(char *zaddr) -{ - struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; - if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) - { - if ( (total= atof(totalstr)) > SMALLVAL ) - { - if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - t_z = z_z = 0; - if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) - { - item = jitem(array,0); - if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) - { - txid = jbits256(item,(char *)"txid"); - bits256_str(txidstr,txid); - if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) - { - ptr->amount = (total * SATOSHIDEN); - ptr->status = 1; - strcpy(ptr->dest,zaddr); - if ( jumblr_addresstype(ptr->dest) != 'z' ) - printf("error setting dest type to Z: %s\n",jprint(item,0)); - if ( jumblr_numvins(txid) == 0 ) - { - z_z = 1; - strcpy(ptr->src,zaddr); - ptr->src[3] = '0'; - ptr->src[4] = '0'; - ptr->src[5] = '0'; - if ( jumblr_addresstype(ptr->src) != 'z' ) - printf("error setting address type to Z: %s\n",jprint(item,0)); - } - else - { - t_z = 1; - strcpy(ptr->src,"taddr"); - if ( jumblr_addresstype(ptr->src) != 't' ) - printf("error setting address type to T: %s\n",jprint(item,0)); - } - printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend - } - } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); - } - free_json(array); - } - free(retstr); - } - } - free(totalstr); - } -} - -void jumblr_opidsupdate() -{ - char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; - if ( (retstr= jumblr_zlistoperationids()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - //printf("%s -> n%d\n",retstr,n); - for (i=0; istatus == 0 ) - jumblr_opidupdate(ptr); - //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); - if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) - jumblr_prune(ptr); - } - } - } - free_json(array); - } - free(retstr); - } -} - -uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) -{ - int32_t i,n; uint64_t incrs[1000],remains = total; - height /= JUMBLR_SYNCHRONIZED_BLOCKS; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) - { - if ( total >= biggest ) - return(biggest); - else if ( total >= medium ) - return(medium); - else if ( total >= smallest ) - return(smallest); - else return(0); - } - else - { - n = 0; - while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) - { - if ( remains >= biggest ) - incrs[n] = biggest; - else if ( remains >= medium ) - incrs[n] = medium; - else if ( remains >= smallest ) - incrs[n] = smallest; - else break; - remains -= incrs[n]; - n++; - } - if ( n > 0 ) - { - r %= n; - for (i=0; i %.8f\n",n,r,dstr(incrs[r])); - return(incrs[r]); - } - } - return(0); -} - -void jumblr_iteration() -{ - static int32_t lastheight; static uint32_t lasttime; - char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; - acpublic = ASSETCHAINS_PUBLIC; - if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) - acpublic = 1; - if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) - return; - if ( lasttime == 0 ) - { - if ( (retstr= jumblr_zlistaddresses()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - for (i=0; iGetHeight(); - if ( time(NULL) < lasttime+40 ) - return; - lasttime = (uint32_t)time(NULL); - if ( lastheight == height ) - return; - lastheight = height; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) - return; - fee = JUMBLR_INCR * JUMBLR_FEE; - smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); - medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); - OS_randombytes((uint8_t *)&r,sizeof(r)); - s = (r % 3); - //printf("jumblr_iteration r.%u s.%u\n",r,s); - switch ( s ) - { - case 0: // t -> z - default: - if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); - /* - amount = 0; - if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); - else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ - if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) - { - printf("sendt_to_z.(%s)\n",retstr); - free(retstr), retstr = 0; - } - free(zaddr); - } else printf("no zaddr from jumblr_zgetnewaddress\n"); - } - else if ( Jumblr_deposit[0] != 0 ) - printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); - break; - case 1: // z -> z - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=counter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) - { - printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); - free(retstr), retstr = 0; - } - ptr->spent = (uint32_t)time(NULL); - free(zaddr); - break; - } - } - counter++; - } - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } - } - break; - case 2: // z -> t - if ( Jumblr_numsecretaddrs > 0 ) - { - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - Jumblr_secretaddr(secretaddr); - if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) - { - printf("%s send z_to_t.(%s)\n",secretaddr,retstr); - free(retstr), retstr = 0; - } else printf("null return from jumblr_sendz_to_t\n"); - ptr->spent = (uint32_t)time(NULL); - break; - } - counter++; - } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); - } - } - break; - } -} +char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount); + +char *jumblr_zlistaddresses(); + +char *jumblr_zlistreceivedbyaddress(char *addr); + +char *jumblr_getreceivedbyaddress(char *addr); + +char *jumblr_importprivkey(char *wifstr); + +char *jumblr_zgetbalance(char *addr); + +char *jumblr_listunspent(char *coinaddr); + +char *jumblr_gettransaction(char *txidstr); + +int32_t jumblr_numvins(bits256 txid); + +int64_t jumblr_receivedby(char *addr); + +int64_t jumblr_balance(char *addr); + +int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status); + +void jumblr_opidupdate(struct jumblr_item *ptr); + +void jumblr_prune(struct jumblr_item *ptr); + +void jumblr_zaddrinit(char *zaddr); + +void jumblr_opidsupdate(); + +uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest); + +void jumblr_iteration(); diff --git a/src/komodo_kv.cpp b/src/komodo_kv.cpp new file mode 100644 index 00000000000..34c0e24b405 --- /dev/null +++ b/src/komodo_kv.cpp @@ -0,0 +1,197 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_kv.h" +#include "komodo_globals.h" // KOMODO_KV_mutex +#include "komodo_utils.h" // portable_mutex_lock + +int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize) +{ + if ( refvalue == 0 && value == 0 ) + return(0); + else if ( refvalue == 0 || value == 0 ) + return(-1); + else if ( refvaluesize != valuesize ) + return(-1); + else return(memcmp(refvalue,value,valuesize)); +} + +int32_t komodo_kvnumdays(uint32_t flags) +{ + int32_t numdays; + if ( (numdays= ((flags>>2)&0x3ff)+1) > 365 ) + numdays = 365; + return(numdays); +} + +int32_t komodo_kvduration(uint32_t flags) +{ + return(komodo_kvnumdays(flags) * KOMODO_KVDURATION); +} + +uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen) +{ + int32_t numdays,k; uint64_t fee; + if ( (k= keylen) > 32 ) + k = 32; + numdays = komodo_kvnumdays(flags); + if ( (fee= (numdays*(opretlen * opretlen / k))) < 100000 ) + fee = 100000; + return(fee); +} + +int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen) +{ + struct komodo_kv *ptr; int32_t duration,retval = -1; + *heightp = -1; + *flagsp = 0; + memset(pubkeyp,0,sizeof(*pubkeyp)); + portable_mutex_lock(&KOMODO_KV_mutex); + HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); + if ( ptr != 0 ) + { + duration = komodo_kvduration(ptr->flags); + //fprintf(stderr,"duration.%d flags.%d current.%d ht.%d keylen.%d valuesize.%d\n",duration,ptr->flags,current_height,ptr->height,ptr->keylen,ptr->valuesize); + if ( current_height > (ptr->height + duration) ) + { + HASH_DELETE(hh,KOMODO_KV,ptr); + if ( ptr->value != 0 ) + free(ptr->value); + if ( ptr->key != 0 ) + free(ptr->key); + free(ptr); + } + else + { + *heightp = ptr->height; + *flagsp = ptr->flags; + int32_t i; for (i=0; i<32; i++) + { + //printf("%02x",((uint8_t *)&ptr->pubkey)[31-i]); + ((uint8_t *)pubkeyp)[i] = ((uint8_t *)&ptr->pubkey)[31-i]; + } + //printf(" ptr->pubkey\n"); + memcpy(pubkeyp,&ptr->pubkey,sizeof(*pubkeyp)); + if ( (retval= ptr->valuesize) > 0 ) + memcpy(value,ptr->value,retval); + } + } //else fprintf(stderr,"couldnt find (%s)\n",(char *)key); + portable_mutex_unlock(&KOMODO_KV_mutex); + if ( retval < 0 ) + { + // search rawmempool + } + return(retval); +} + +void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) +{ + static uint256 zeroes; + uint32_t flags; uint256 pubkey,refpubkey,sig; int32_t i,refvaluesize,hassig,coresize,haspubkey,height,kvheight; uint16_t keylen,valuesize,newflag = 0; uint8_t *key,*valueptr,keyvalue[IGUANA_MAXSCRIPTSIZE*8]; struct komodo_kv *ptr; char *transferpubstr,*tstr; uint64_t fee; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) // disable KV for KMD + return; + iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); + iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); + iguana_rwnum(0,&opretbuf[5],sizeof(height),&height); + iguana_rwnum(0,&opretbuf[9],sizeof(flags),&flags); + key = &opretbuf[13]; + if ( keylen+13 > opretlen ) + { + static uint32_t counter; + if ( ++counter < 1 ) + fprintf(stderr,"komodo_kvupdate: keylen.%d + 13 > opretlen.%d, this can be ignored\n",keylen,opretlen); + return; + } + valueptr = &key[keylen]; + fee = komodo_kvfee(flags,opretlen,keylen); + //fprintf(stderr,"fee %.8f vs %.8f flags.%d keylen.%d valuesize.%d height.%d (%02x %02x %02x) (%02x %02x %02x)\n",(double)fee/COIN,(double)value/COIN,flags,keylen,valuesize,height,key[0],key[1],key[2],valueptr[0],valueptr[1],valueptr[2]); + if ( value >= fee ) + { + coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(keylen)+sizeof(valuesize)+keylen+valuesize+1); + if ( opretlen == coresize || opretlen == coresize+sizeof(uint256) || opretlen == coresize+2*sizeof(uint256) ) + { + memset(&pubkey,0,sizeof(pubkey)); + memset(&sig,0,sizeof(sig)); + if ( (haspubkey= (opretlen >= coresize+sizeof(uint256))) != 0 ) + { + for (i=0; i<32; i++) + ((uint8_t *)&pubkey)[i] = opretbuf[coresize+i]; + } + if ( (hassig= (opretlen == coresize+sizeof(uint256)*2)) != 0 ) + { + for (i=0; i<32; i++) + ((uint8_t *)&sig)[i] = opretbuf[coresize+sizeof(uint256)+i]; + } + memcpy(keyvalue,key,keylen); + if ( (refvaluesize= komodo_kvsearch((uint256 *)&refpubkey,height,&flags,&kvheight,&keyvalue[keylen],key,keylen)) >= 0 ) + { + if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) + { + if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 ) + { + //fprintf(stderr,"komodo_kvsigverify error [%d]\n",coresize-13); + return; + } + } + } + portable_mutex_lock(&KOMODO_KV_mutex); + HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); + if ( ptr != 0 ) + { + //fprintf(stderr,"(%s) already there\n",(char *)key); + //if ( (ptr->flags & KOMODO_KVPROTECTED) != 0 ) + { + tstr = (char *)"transfer:"; + transferpubstr = (char *)&valueptr[strlen(tstr)]; + if ( strncmp(tstr,(char *)valueptr,strlen(tstr)) == 0 && is_hexstr(transferpubstr,0) == 64 ) + { + printf("transfer.(%s) to [%s]? ishex.%d\n",key,transferpubstr,is_hexstr(transferpubstr,0)); + for (i=0; i<32; i++) + ((uint8_t *)&pubkey)[31-i] = _decode_hex(&transferpubstr[i*2]); + } + } + } + else if ( ptr == 0 ) + { + ptr = (struct komodo_kv *)calloc(1,sizeof(*ptr)); + ptr->key = (uint8_t *)calloc(1,keylen); + ptr->keylen = keylen; + memcpy(ptr->key,key,keylen); + newflag = 1; + HASH_ADD_KEYPTR(hh,KOMODO_KV,ptr->key,ptr->keylen,ptr); + //fprintf(stderr,"KV add.(%s) (%s)\n",ptr->key,valueptr); + } + if ( newflag != 0 || (ptr->flags & KOMODO_KVPROTECTED) == 0 ) + { + if ( ptr->value != 0 ) + free(ptr->value), ptr->value = 0; + if ( (ptr->valuesize= valuesize) != 0 ) + { + ptr->value = (uint8_t *)calloc(1,valuesize); + memcpy(ptr->value,valueptr,valuesize); + } + } else fprintf(stderr,"newflag.%d zero or protected %d\n",newflag,(ptr->flags & KOMODO_KVPROTECTED)); + /*for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&ptr->pubkey)[i]); + printf(" <- "); + for (i=0; i<32; i++) + printf("%02x",((uint8_t *)&pubkey)[i]); + printf(" new pubkey\n");*/ + memcpy(&ptr->pubkey,&pubkey,sizeof(ptr->pubkey)); + ptr->height = height; + ptr->flags = flags; // jl777 used to or in KVPROTECTED + portable_mutex_unlock(&KOMODO_KV_mutex); + } else fprintf(stderr,"KV update size mismatch %d vs %d\n",opretlen,coresize); + } else fprintf(stderr,"not enough fee\n"); +} diff --git a/src/komodo_kv.h b/src/komodo_kv.h index a879340ffea..6ed489ac49a 100644 --- a/src/komodo_kv.h +++ b/src/komodo_kv.h @@ -12,190 +12,18 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - -#ifndef H_KOMODOKV_H -#define H_KOMODOKV_H +#pragma once #include "komodo_defs.h" -int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize) -{ - if ( refvalue == 0 && value == 0 ) - return(0); - else if ( refvalue == 0 || value == 0 ) - return(-1); - else if ( refvaluesize != valuesize ) - return(-1); - else return(memcmp(refvalue,value,valuesize)); -} - -int32_t komodo_kvnumdays(uint32_t flags) -{ - int32_t numdays; - if ( (numdays= ((flags>>2)&0x3ff)+1) > 365 ) - numdays = 365; - return(numdays); -} +int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize); -int32_t komodo_kvduration(uint32_t flags) -{ - return(komodo_kvnumdays(flags) * KOMODO_KVDURATION); -} +int32_t komodo_kvnumdays(uint32_t flags); -uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen) -{ - int32_t numdays,k; uint64_t fee; - if ( (k= keylen) > 32 ) - k = 32; - numdays = komodo_kvnumdays(flags); - if ( (fee= (numdays*(opretlen * opretlen / k))) < 100000 ) - fee = 100000; - return(fee); -} +int32_t komodo_kvduration(uint32_t flags); -int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen) -{ - struct komodo_kv *ptr; int32_t duration,retval = -1; - *heightp = -1; - *flagsp = 0; - memset(pubkeyp,0,sizeof(*pubkeyp)); - portable_mutex_lock(&KOMODO_KV_mutex); - HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); - if ( ptr != 0 ) - { - duration = komodo_kvduration(ptr->flags); - //fprintf(stderr,"duration.%d flags.%d current.%d ht.%d keylen.%d valuesize.%d\n",duration,ptr->flags,current_height,ptr->height,ptr->keylen,ptr->valuesize); - if ( current_height > (ptr->height + duration) ) - { - HASH_DELETE(hh,KOMODO_KV,ptr); - if ( ptr->value != 0 ) - free(ptr->value); - if ( ptr->key != 0 ) - free(ptr->key); - free(ptr); - } - else - { - *heightp = ptr->height; - *flagsp = ptr->flags; - int32_t i; for (i=0; i<32; i++) - { - //printf("%02x",((uint8_t *)&ptr->pubkey)[31-i]); - ((uint8_t *)pubkeyp)[i] = ((uint8_t *)&ptr->pubkey)[31-i]; - } - //printf(" ptr->pubkey\n"); - memcpy(pubkeyp,&ptr->pubkey,sizeof(*pubkeyp)); - if ( (retval= ptr->valuesize) > 0 ) - memcpy(value,ptr->value,retval); - } - } //else fprintf(stderr,"couldnt find (%s)\n",(char *)key); - portable_mutex_unlock(&KOMODO_KV_mutex); - if ( retval < 0 ) - { - // search rawmempool - } - return(retval); -} +uint64_t komodo_kvfee(uint32_t flags,int32_t opretlen,int32_t keylen); -void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value) -{ - static uint256 zeroes; - uint32_t flags; uint256 pubkey,refpubkey,sig; int32_t i,refvaluesize,hassig,coresize,haspubkey,height,kvheight; uint16_t keylen,valuesize,newflag = 0; uint8_t *key,*valueptr,keyvalue[IGUANA_MAXSCRIPTSIZE*8]; struct komodo_kv *ptr; char *transferpubstr,*tstr; uint64_t fee; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) // disable KV for KMD - return; - iguana_rwnum(0,&opretbuf[1],sizeof(keylen),&keylen); - iguana_rwnum(0,&opretbuf[3],sizeof(valuesize),&valuesize); - iguana_rwnum(0,&opretbuf[5],sizeof(height),&height); - iguana_rwnum(0,&opretbuf[9],sizeof(flags),&flags); - key = &opretbuf[13]; - if ( keylen+13 > opretlen ) - { - static uint32_t counter; - if ( ++counter < 1 ) - fprintf(stderr,"komodo_kvupdate: keylen.%d + 13 > opretlen.%d, this can be ignored\n",keylen,opretlen); - return; - } - valueptr = &key[keylen]; - fee = komodo_kvfee(flags,opretlen,keylen); - //fprintf(stderr,"fee %.8f vs %.8f flags.%d keylen.%d valuesize.%d height.%d (%02x %02x %02x) (%02x %02x %02x)\n",(double)fee/COIN,(double)value/COIN,flags,keylen,valuesize,height,key[0],key[1],key[2],valueptr[0],valueptr[1],valueptr[2]); - if ( value >= fee ) - { - coresize = (int32_t)(sizeof(flags)+sizeof(height)+sizeof(keylen)+sizeof(valuesize)+keylen+valuesize+1); - if ( opretlen == coresize || opretlen == coresize+sizeof(uint256) || opretlen == coresize+2*sizeof(uint256) ) - { - memset(&pubkey,0,sizeof(pubkey)); - memset(&sig,0,sizeof(sig)); - if ( (haspubkey= (opretlen >= coresize+sizeof(uint256))) != 0 ) - { - for (i=0; i<32; i++) - ((uint8_t *)&pubkey)[i] = opretbuf[coresize+i]; - } - if ( (hassig= (opretlen == coresize+sizeof(uint256)*2)) != 0 ) - { - for (i=0; i<32; i++) - ((uint8_t *)&sig)[i] = opretbuf[coresize+sizeof(uint256)+i]; - } - memcpy(keyvalue,key,keylen); - if ( (refvaluesize= komodo_kvsearch((uint256 *)&refpubkey,height,&flags,&kvheight,&keyvalue[keylen],key,keylen)) >= 0 ) - { - if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) - { - if ( komodo_kvsigverify(keyvalue,keylen+refvaluesize,refpubkey,sig) < 0 ) - { - //fprintf(stderr,"komodo_kvsigverify error [%d]\n",coresize-13); - return; - } - } - } - portable_mutex_lock(&KOMODO_KV_mutex); - HASH_FIND(hh,KOMODO_KV,key,keylen,ptr); - if ( ptr != 0 ) - { - //fprintf(stderr,"(%s) already there\n",(char *)key); - //if ( (ptr->flags & KOMODO_KVPROTECTED) != 0 ) - { - tstr = (char *)"transfer:"; - transferpubstr = (char *)&valueptr[strlen(tstr)]; - if ( strncmp(tstr,(char *)valueptr,strlen(tstr)) == 0 && is_hexstr(transferpubstr,0) == 64 ) - { - printf("transfer.(%s) to [%s]? ishex.%d\n",key,transferpubstr,is_hexstr(transferpubstr,0)); - for (i=0; i<32; i++) - ((uint8_t *)&pubkey)[31-i] = _decode_hex(&transferpubstr[i*2]); - } - } - } - else if ( ptr == 0 ) - { - ptr = (struct komodo_kv *)calloc(1,sizeof(*ptr)); - ptr->key = (uint8_t *)calloc(1,keylen); - ptr->keylen = keylen; - memcpy(ptr->key,key,keylen); - newflag = 1; - HASH_ADD_KEYPTR(hh,KOMODO_KV,ptr->key,ptr->keylen,ptr); - //fprintf(stderr,"KV add.(%s) (%s)\n",ptr->key,valueptr); - } - if ( newflag != 0 || (ptr->flags & KOMODO_KVPROTECTED) == 0 ) - { - if ( ptr->value != 0 ) - free(ptr->value), ptr->value = 0; - if ( (ptr->valuesize= valuesize) != 0 ) - { - ptr->value = (uint8_t *)calloc(1,valuesize); - memcpy(ptr->value,valueptr,valuesize); - } - } else fprintf(stderr,"newflag.%d zero or protected %d\n",newflag,(ptr->flags & KOMODO_KVPROTECTED)); - /*for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&ptr->pubkey)[i]); - printf(" <- "); - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&pubkey)[i]); - printf(" new pubkey\n");*/ - memcpy(&ptr->pubkey,&pubkey,sizeof(ptr->pubkey)); - ptr->height = height; - ptr->flags = flags; // jl777 used to or in KVPROTECTED - portable_mutex_unlock(&KOMODO_KV_mutex); - } else fprintf(stderr,"KV update size mismatch %d vs %d\n",opretlen,coresize); - } else fprintf(stderr,"not enough fee\n"); -} +int32_t komodo_kvsearch(uint256 *pubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -#endif +void komodo_kvupdate(uint8_t *opretbuf,int32_t opretlen,uint64_t value); diff --git a/src/komodo_notary.cpp b/src/komodo_notary.cpp new file mode 100644 index 00000000000..c43a87e705a --- /dev/null +++ b/src/komodo_notary.cpp @@ -0,0 +1,1297 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_notary.h" + +const char *Notaries_genesis[][2] = +{ + { "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "crackers_EU", "0340c66cf2c41c41efb420af57867baa765e8468c12aa996bfd816e1e07e410728" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "locomb_EU", "025c6d26649b9d397e63323d96db42a9d3caad82e1d6076970efe5056c00c0779b" }, + { "fullmoon_AE", "0204a908350b8142698fdb6fabefc97fe0e04f537adc7522ba7a1e8f3bec003d4a" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "crackers_NA", "029e1c01131974f4cd3f564cc0c00eb87a0f9721043fbc1ca60f9bd0a1f73f64a1" }, + { "proto_EU", "03681ffdf17c8f4f0008cefb7fa0779c5e888339cdf932f0974483787a4d6747c1" }, // 10 + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "farl4web_EU", "035caa40684ace968677dca3f09098aa02b70e533da32390a7654c626e0cf908e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "traderbill_EU", "03196e8de3e2e5d872f31d79d6a859c8704a2198baf0af9c7b21e29656a7eb455f" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 15 + { "titomane_EU", "03517fcac101fed480ae4f2caf775560065957930d8c1facc83e30077e45bdd199" }, + { "supernet_AE", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, + { "supernet_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "supernet_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "yassin_EU", "033fb7231bb66484081952890d9a03f91164fb27d392d9152ec41336b71b15fbd0" }, // 20 + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "rnr_EU", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "crackers_SH", "02313d72f9a16055737e14cfc528dcd5d0ef094cfce23d0348fe974b6b1a32e5f0" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "polycryptoblock_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "titomane_NA", "0387046d9745414fb58a0fa3599078af5073e10347e4657ef7259a99cb4f10ad47" }, + { "titomane_AE", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "kolo_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "eclips_EU", "0339369c1f5a2028d44be7be6f8ec3b907fdec814f87d2dead97cab4edb71a42e9" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, +}; + +int32_t getkmdseason(int32_t height) +{ + if ( height <= KMD_SEASON_HEIGHTS[0] ) + return(1); + for (int32_t i = 1; i < NUM_KMD_SEASONS; i++) + { + if ( height <= KMD_SEASON_HEIGHTS[i] && height > KMD_SEASON_HEIGHTS[i-1] ) + return(i+1); + } + return(0); +} + +int32_t getacseason(uint32_t timestamp) +{ + if ( timestamp <= KMD_SEASON_TIMESTAMPS[0] ) + return(1); + for (int32_t i = 1; i < NUM_KMD_SEASONS; i++) + { + if ( timestamp <= KMD_SEASON_TIMESTAMPS[i] && timestamp > KMD_SEASON_TIMESTAMPS[i-1] ) + return(i+1); + } + return(0); +} + +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) +{ + int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp; + static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33],didinit[NUM_KMD_SEASONS]; + + if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + timestamp = komodo_heightstamp(height); + else if ( ASSETCHAINS_SYMBOL[0] == 0 ) + timestamp = 0; + + // If this chain is not a staked chain, use the normal Komodo logic to determine notaries. This allows KMD to still sync and use its proper pubkeys for dPoW. + if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 ) + { + int32_t kmd_season = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + // This is KMD, use block heights to determine the KMD notary season.. + if ( height >= KOMODO_NOTARIES_HARDCODED ) + kmd_season = getkmdseason(height); + } + else + { + // This is a non LABS assetchain, use timestamp to detemine notary pubkeys. + kmd_season = getacseason(timestamp); + } + if ( kmd_season != 0 ) + { + if ( didinit[kmd_season-1] == 0 ) + { + for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + if ( Pubkeys == 0 ) + { + komodo_init(height); + //printf("Pubkeys.%p htind.%d vs max.%d\n",Pubkeys,htind,KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP); + } + { + std::lock_guard lock(komodo_mutex); + n = Pubkeys[htind].numnotaries; + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"%s height.%d t.%u genesis.%d\n",ASSETCHAINS_SYMBOL,height,timestamp,n); + HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) + { + if ( kp->notaryid < n ) + { + mask |= (1LL << kp->notaryid); + memcpy(pubkeys[kp->notaryid],kp->pubkey,33); + } else printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); + } + } + if ( (n < 64 && mask == ((1LL << n)-1)) || (n == 64 && mask == 0xffffffffffffffffLL) ) + return(n); + printf("error retrieving notaries ht.%d got mask.%llx for n.%d\n",height,(long long)mask,n); + return(-1); +} + +int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp) +{ + int32_t i,n; uint8_t pubkeys[64][33]; + n = komodo_notaries(pubkeys,height,timestamp); + *numnotariesp = n; + for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + numnotaries = Pubkeys[htind].numnotaries; + for (i=0; i (numnotaries >> 1) || (wt > 7 && (signedmask & 1) != 0) ) + return(1); + else return(0); +} + +void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num) +{ + static int32_t hwmheight; + int32_t k,i,htind,height; struct knotary_entry *kp; struct knotaries_entry N; + if ( Pubkeys == 0 ) + Pubkeys = (struct knotaries_entry *)calloc(1 + (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP),sizeof(*Pubkeys)); + memset(&N,0,sizeof(N)); + if ( origheight > 0 ) + { + height = (origheight + KOMODO_ELECTION_GAP/2); + height /= KOMODO_ELECTION_GAP; + height = ((height + 1) * KOMODO_ELECTION_GAP); + htind = (height / KOMODO_ELECTION_GAP); + if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + //printf("htind.%d activation %d from %d vs %d | hwmheight.%d %s\n",htind,height,origheight,(((origheight+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,hwmheight,ASSETCHAINS_SYMBOL); + } else htind = 0; + { + std::lock_guard lock(komodo_mutex); + for (k=0; kpubkey,pubkeys[k],33); + kp->notaryid = k; + HASH_ADD_KEYPTR(hh,N.Notaries,kp->pubkey,33,kp); + if ( 0 && height > 10000 ) + { + for (i=0; i<33; i++) + printf("%02x",pubkeys[k][i]); + printf(" notarypubs.[%d] ht.%d active at %d\n",k,origheight,htind*KOMODO_ELECTION_GAP); + } + } + N.numnotaries = num; + for (i=htind; i hwmheight ) + hwmheight = origheight; +} + +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp) +{ + // -1 if not notary, 0 if notary, 1 if special notary + struct knotary_entry *kp; int32_t numnotaries=0,htind,modval = -1; + *notaryidp = -1; + if ( height < 0 )//|| height >= KOMODO_MAXBLOCKS ) + { + printf("komodo_chosennotary ht.%d illegal\n",height); + return(-1); + } + if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 ) + { + if ( (*notaryidp= komodo_electednotary(&numnotaries,pubkey33,height,timestamp)) >= 0 && numnotaries != 0 ) + { + modval = ((height % numnotaries) == *notaryidp); + return(modval); + } + } + if ( height >= 250000 ) + return(-1); + if ( Pubkeys == 0 ) + komodo_init(0); + htind = height / KOMODO_ELECTION_GAP; + if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) + htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; + { + std::lock_guard lock(komodo_mutex); + HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); + } + if ( kp != 0 ) + { + if ( (numnotaries= Pubkeys[htind].numnotaries) > 0 ) + { + *notaryidp = kp->notaryid; + modval = ((height % numnotaries) == kp->notaryid); + //printf("found notary.%d ht.%d modval.%d\n",kp->notaryid,height,modval); + } else printf("unexpected zero notaries at height.%d\n",height); + } //else printf("cant find kp at htind.%d ht.%d\n",htind,height); + //int32_t i; for (i=0; i<33; i++) + // printf("%02x",pubkey33[i]); + //printf(" ht.%d notary.%d special.%d htind.%d num.%d\n",height,*notaryidp,modval,htind,numnotaries); + return(modval); +} + +//struct komodo_state *komodo_stateptr(char *symbol,char *dest); + +struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + for (i=sp->NUM_NPOINTS-1; i>=0; i--) + { + *idx = i; + np = &sp->NPOINTS[i]; + if ( np->MoMdepth != 0 && height > np->notarized_height-(np->MoMdepth&0xffff) && height <= np->notarized_height ) + return(np); + } + } + *idx = -1; + return(0); +} + +struct notarized_checkpoint *komodo_npptr(int32_t height) +{ + int idx; + return komodo_npptr_for_height(height, &idx); +} + +struct notarized_checkpoint *komodo_npptr_at(int idx) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + if (idx < sp->NUM_NPOINTS) + return &sp->NPOINTS[idx]; + return(0); +} + +int32_t komodo_prevMoMheight() +{ + static uint256 zero; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + for (i=sp->NUM_NPOINTS-1; i>=0; i--) + { + np = &sp->NPOINTS[i]; + if ( np->MoM != zero ) + return(np->notarized_height); + } + } + return(0); +} + +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp) +{ + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + *prevMoMheightp = 0; + memset(hashp,0,sizeof(*hashp)); + memset(txidp,0,sizeof(*txidp)); + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + CBlockIndex *pindex; + if ( (pindex= komodo_blockindex(sp->NOTARIZED_HASH)) == 0 || pindex->GetHeight() < 0 ) + { + //fprintf(stderr,"found orphaned notarization at ht.%d pindex.%p\n",sp->NOTARIZED_HEIGHT,(void *)pindex); + memset(&sp->NOTARIZED_HASH,0,sizeof(sp->NOTARIZED_HASH)); + memset(&sp->NOTARIZED_DESTTXID,0,sizeof(sp->NOTARIZED_DESTTXID)); + sp->NOTARIZED_HEIGHT = 0; + } + else + { + *hashp = sp->NOTARIZED_HASH; + *txidp = sp->NOTARIZED_DESTTXID; + *prevMoMheightp = komodo_prevMoMheight(); + } + return(sp->NOTARIZED_HEIGHT); + } else return(0); +} + +int32_t komodo_dpowconfs(int32_t txheight,int32_t numconfs) +{ + static int32_t hadnotarization; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( KOMODO_DPOWCONFS != 0 && txheight > 0 && numconfs > 0 && (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + if ( sp->NOTARIZED_HEIGHT > 0 ) + { + hadnotarization = 1; + if ( txheight < sp->NOTARIZED_HEIGHT ) + return(numconfs); + else return(1); + } + else if ( hadnotarization != 0 ) + return(1); + } + return(numconfs); +} + +int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) +{ + struct notarized_checkpoint *np = 0; + if ( (np= komodo_npptr(height)) != 0 ) + { + *notarized_htp = np->notarized_height; + *MoMp = np->MoM; + *kmdtxidp = np->notarized_desttxid; + *MoMoMp = np->MoMoM; + *MoMoMoffsetp = np->MoMoMoffset; + *MoMoMdepthp = np->MoMoMdepth; + *kmdstartip = np->kmdstarti; + *kmdendip = np->kmdendi; + return(np->MoMdepth & 0xffff); + } + *notarized_htp = *MoMoMoffsetp = *MoMoMdepthp = *kmdstartip = *kmdendip = 0; + memset(MoMp,0,sizeof(*MoMp)); + memset(MoMoMp,0,sizeof(*MoMoMp)); + memset(kmdtxidp,0,sizeof(*kmdtxidp)); + return(0); +} + +int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp) +{ + struct notarized_checkpoint *np = 0; int32_t i=0,flag = 0; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) + { + if ( sp->NUM_NPOINTS > 0 ) + { + flag = 0; + if ( sp->last_NPOINTSi < sp->NUM_NPOINTS && sp->last_NPOINTSi > 0 ) + { + np = &sp->NPOINTS[sp->last_NPOINTSi-1]; + if ( np->nHeight < nHeight ) + { + for (i=sp->last_NPOINTSi; iNUM_NPOINTS; i++) + { + if ( sp->NPOINTS[i].nHeight >= nHeight ) + { + //printf("flag.1 i.%d np->ht %d [%d].ht %d >= nHeight.%d, last.%d num.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight,sp->last_NPOINTSi,sp->NUM_NPOINTS); + flag = 1; + break; + } + np = &sp->NPOINTS[i]; + sp->last_NPOINTSi = i; + } + } + } + if ( flag == 0 ) + { + np = 0; + for (i=0; iNUM_NPOINTS; i++) + { + if ( sp->NPOINTS[i].nHeight >= nHeight ) + { + //printf("i.%d np->ht %d [%d].ht %d >= nHeight.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight); + break; + } + np = &sp->NPOINTS[i]; + sp->last_NPOINTSi = i; + } + } + } + if ( np != 0 ) + { + //char str[65],str2[65]; printf("[%s] notarized_ht.%d\n",ASSETCHAINS_SYMBOL,np->notarized_height); + if ( np->nHeight >= nHeight || (i < sp->NUM_NPOINTS && np[1].nHeight < nHeight) ) + printf("warning: flag.%d i.%d np->ht %d [1].ht %d >= nHeight.%d\n",flag,i,np->nHeight,np[1].nHeight,nHeight); + *notarized_hashp = np->notarized_hash; + *notarized_desttxidp = np->notarized_desttxid; + return(np->notarized_height); + } + } + memset(notarized_hashp,0,sizeof(*notarized_hashp)); + memset(notarized_desttxidp,0,sizeof(*notarized_desttxidp)); + return(0); +} + +void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_desttxid,uint256 MoM,int32_t MoMdepth) +{ + struct notarized_checkpoint *np; + if ( notarized_height >= nHeight ) + { + fprintf(stderr,"komodo_notarized_update REJECT notarized_height %d > %d nHeight\n",notarized_height,nHeight); + return; + } + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); + /****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ + +/* + z_exportkey "zaddr" + z_exportwallet "filename" + z_getoperationstatus (["operationid", ... ]) + z_gettotalbalance ( minconf ) + z_importkey "zkey" ( rescan ) + z_importwallet "filename" + z_listaddresses + z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":""},...] ( minconf ) ( fee ) + */ + +#ifdef _WIN32 +#include +#endif +#include "komodo_defs.h" + +#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" +#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" +#define JUMBLR_MAXSECRETADDRS 777 +#define JUMBLR_SYNCHRONIZED_BLOCKS 10 +#define JUMBLR_INCR 9.965 +#define JUMBLR_FEE 0.001 +#define JUMBLR_TXFEE 0.01 +#define SMALLVAL 0.000000000000001 + +#define JUMBLR_ERROR_DUPLICATEDEPOSIT -1 +#define JUMBLR_ERROR_SECRETCANTBEDEPOSIT -2 +#define JUMBLR_ERROR_TOOMANYSECRETS -3 +#define JUMBLR_ERROR_NOTINWALLET -4 + +struct jumblr_item +{ + UT_hash_handle hh; + int64_t amount,fee,txfee; // fee and txfee not really used (yet) + uint32_t spent,pad; + char opid[66],src[128],dest[128],status; +} *Jumblrs; + +char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64]; +int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode + +char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) +{ + cJSON *retjson,*resjson = 0; char *retstr; + if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,(char *)"result") != 0 ) + resjson = jduplicate(jobj(retjson,(char *)"result")); + else if ( jobj(retjson,(char *)"error") != 0 ) + resjson = jduplicate(jobj(retjson,(char *)"error")); + else + { + resjson = cJSON_CreateObject(); + jaddstr(resjson,(char *)"error",(char *)"cant parse return"); + } + free_json(retjson); + } + free(retstr); + } + if ( resjson != 0 ) + return(jprint(resjson,1)); + else return(clonestr((char *)"{\"error\":\"unknown error\"}")); +} + +char *jumblr_importaddress(char *address) +{ + char params[1024]; + sprintf(params,"[\"%s\", \"%s\", false]",address,address); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_validateaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\"]",addr); + printf("validateaddress.%s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); +} + +int32_t Jumblr_secretaddrfind(char *searchaddr) +{ + int32_t i; + for (i=0; i 0 ) + { + OS_randombytes((uint8_t *)&r,sizeof(r)); + r %= Jumblr_numsecretaddrs; + safecopy(secretaddr,Jumblr_secretaddrs[r],64); + } + return(r); +} + +int32_t jumblr_addresstype(char *addr) +{ + if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) + { + addr[strlen(addr)-1] = 0; + addr++; + } + if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) + return('z'); + else if ( strlen(addr) < 40 ) + return('t'); + printf("strange.(%s)\n",addr); + return(-1); +} + +struct jumblr_item *jumblr_opidfind(char *opid) +{ + struct jumblr_item *ptr; + HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); + return(ptr); +} + +struct jumblr_item *jumblr_opidadd(char *opid) +{ + struct jumblr_item *ptr = 0; + if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) + { + ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); + safecopy(ptr->opid,opid,sizeof(ptr->opid)); + HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); + if ( ptr != jumblr_opidfind(opid) ) + printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); + } + return(ptr); +} + +char *jumblr_zgetnewaddress() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistoperationids() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetoperationresult(char *opid) +{ + char params[1024]; + sprintf(params,"[[\"%s\"]]",opid); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetoperationstatus(char *opid) +{ + char params[1024]; + sprintf(params,"[[\"%s\"]]",opid); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) +{ + char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; + if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) + return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + printf("t -> z: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) +{ + char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; + if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) + return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); + //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); + printf("z -> z: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) +{ + char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; + if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) + return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); + sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); + printf("z -> t: %s\n",params); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistaddresses() +{ + char params[1024]; + sprintf(params,"[]"); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zlistreceivedbyaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_getreceivedbyaddress(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); +} + +char *jumblr_importprivkey(char *wifstr) +{ + char params[1024]; + sprintf(params,"[\"%s\", \"\", false]",wifstr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); +} + +char *jumblr_zgetbalance(char *addr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",addr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); +} + +char *jumblr_listunspent(char *coinaddr) +{ + char params[1024]; + sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); +} + +char *jumblr_gettransaction(char *txidstr) +{ + char params[1024]; + sprintf(params,"[\"%s\", 1]",txidstr); + return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); +} + +int32_t jumblr_numvins(bits256 txid) +{ + char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; + bits256_str(txidstr,txid); + if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) + { + numvins = n; + //printf("numvins.%d\n",n); + } //else printf("no vin.(%s)\n",retstr); + free_json(retjson); + } + free(retstr); + } + return(numvins); +} + +int64_t jumblr_receivedby(char *addr) +{ + char *retstr; int64_t total = 0; + if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) + { + total = atof(retstr) * SATOSHIDEN; + free(retstr); + } + return(total); +} + +int64_t jumblr_balance(char *addr) +{ + char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; + /*if ( jumblr_addresstype(addr) == 't' ) + { + if ( (retstr= jumblr_listunspent(addr)) != 0 ) + { + //printf("jumblr.[%s].(%s)\n","KMD",retstr); + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) + for (i=0; i SMALLVAL ) + balance = val * SATOSHIDEN; + free(retstr); + } + return(balance); +} + +int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) +{ + cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; + /*"params" : { + "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", + "amounts" : [ + { + "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", + "amount" : 3.00000000 + } + ], + "minconf" : 1, + "fee" : 0.00010000 + }*/ + if ( (params= jobj(item,(char *)"params")) != 0 ) + { + //printf("params.(%s)\n",jprint(params,0)); + if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) + { + safecopy(ptr->src,from,sizeof(ptr->src)); + } + if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) + { + for (i=0; i 0 ) + { + if ( strcmp(addr,JUMBLR_ADDR) == 0 ) + ptr->fee = amount; + else + { + ptr->amount = amount; + safecopy(ptr->dest,addr,sizeof(ptr->dest)); + } + } + } + } + ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; + } + return(1); +} + +void jumblr_opidupdate(struct jumblr_item *ptr) +{ + char *retstr,*status; cJSON *retjson,*item; + if ( ptr->status == 0 ) + { + if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) + { + item = jitem(retjson,0); + //printf("%s\n",jprint(item,0)); + if ( (status= jstr(item,(char *)"status")) != 0 ) + { + if ( strcmp(status,(char *)"success") == 0 ) + { + ptr->status = jumblr_itemset(ptr,item,status); + if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) + { + printf("a non-jumblr t->z pruned\n"); + free(jumblr_zgetoperationresult(ptr->opid)); + ptr->status = -1; + } + + } + else if ( strcmp(status,(char *)"failed") == 0 ) + { + printf("jumblr_opidupdate %s failed\n",ptr->opid); + free(jumblr_zgetoperationresult(ptr->opid)); + ptr->status = -1; + } + } + } + free_json(retjson); + } + free(retstr); + } + } +} + +void jumblr_prune(struct jumblr_item *ptr) +{ + struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; + if ( is_hexstr(ptr->opid,0) == 64 ) + return; + printf("jumblr_prune %s\n",ptr->opid); + strcpy(oldsrc,ptr->src); + free(jumblr_zgetoperationresult(ptr->opid)); + while ( flag != 0 ) + { + flag = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + if ( strcmp(oldsrc,ptr->dest) == 0 ) + { + if ( is_hexstr(ptr->opid,0) != 64 ) + { + printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); + free(jumblr_zgetoperationresult(ptr->opid)); + strcpy(oldsrc,ptr->src); + flag = 1; + break; + } + } + } + } +} + + +bits256 jbits256(cJSON *json,char *field); + + +void jumblr_zaddrinit(char *zaddr) +{ + struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; + if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) + { + if ( (total= atof(totalstr)) > SMALLVAL ) + { + if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + t_z = z_z = 0; + if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) + { + item = jitem(array,0); + if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) + { + txid = jbits256(item,(char *)"txid"); + bits256_str(txidstr,txid); + if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) + { + ptr->amount = (total * SATOSHIDEN); + ptr->status = 1; + strcpy(ptr->dest,zaddr); + if ( jumblr_addresstype(ptr->dest) != 'z' ) + printf("error setting dest type to Z: %s\n",jprint(item,0)); + if ( jumblr_numvins(txid) == 0 ) + { + z_z = 1; + strcpy(ptr->src,zaddr); + ptr->src[3] = '0'; + ptr->src[4] = '0'; + ptr->src[5] = '0'; + if ( jumblr_addresstype(ptr->src) != 'z' ) + printf("error setting address type to Z: %s\n",jprint(item,0)); + } + else + { + t_z = 1; + strcpy(ptr->src,"taddr"); + if ( jumblr_addresstype(ptr->src) != 't' ) + printf("error setting address type to T: %s\n",jprint(item,0)); + } + printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend + } + } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); + } + free_json(array); + } + free(retstr); + } + } + free(totalstr); + } +} + +void jumblr_opidsupdate() +{ + char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; + if ( (retstr= jumblr_zlistoperationids()) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) + { + //printf("%s -> n%d\n",retstr,n); + for (i=0; istatus == 0 ) + jumblr_opidupdate(ptr); + //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); + if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) + jumblr_prune(ptr); + } + } + } + free_json(array); + } + free(retstr); + } +} + +uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) +{ + int32_t i,n; uint64_t incrs[1000],remains = total; + height /= JUMBLR_SYNCHRONIZED_BLOCKS; + if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) + { + if ( total >= biggest ) + return(biggest); + else if ( total >= medium ) + return(medium); + else if ( total >= smallest ) + return(smallest); + else return(0); + } + else + { + n = 0; + while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) + { + if ( remains >= biggest ) + incrs[n] = biggest; + else if ( remains >= medium ) + incrs[n] = medium; + else if ( remains >= smallest ) + incrs[n] = smallest; + else break; + remains -= incrs[n]; + n++; + } + if ( n > 0 ) + { + r %= n; + for (i=0; i %.8f\n",n,r,dstr(incrs[r])); + return(incrs[r]); + } + } + return(0); +} + +void jumblr_iteration() +{ + static int32_t lastheight; static uint32_t lasttime; + char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; + acpublic = ASSETCHAINS_PUBLIC; + if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) + acpublic = 1; + if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) + return; + if ( lasttime == 0 ) + { + if ( (retstr= jumblr_zlistaddresses()) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) + { + for (i=0; iGetHeight(); + if ( time(NULL) < lasttime+40 ) + return; + lasttime = (uint32_t)time(NULL); + if ( lastheight == height ) + return; + lastheight = height; + if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) + return; + fee = JUMBLR_INCR * JUMBLR_FEE; + smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); + medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); + biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); + OS_randombytes((uint8_t *)&r,sizeof(r)); + s = (r % 3); + //printf("jumblr_iteration r.%u s.%u\n",r,s); + switch ( s ) + { + case 0: // t -> z + default: + if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) + { + if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) + { + if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) + { + zaddr[strlen(zaddr)-1] = 0; + addr = zaddr+1; + } else addr = zaddr; + amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); + /* + amount = 0; + if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) + amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); + else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) + amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); + else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ + if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) + { + printf("sendt_to_z.(%s)\n",retstr); + free(retstr), retstr = 0; + } + free(zaddr); + } else printf("no zaddr from jumblr_zgetnewaddress\n"); + } + else if ( Jumblr_deposit[0] != 0 ) + printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); + break; + case 1: // z -> z + jumblr_opidsupdate(); + chosen_one = -1; + for (iter=counter=0; iter<2; iter++) + { + counter = n = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) + { + if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + { + if ( iter == 1 && counter == chosen_one ) + { + if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) + { + if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) + { + zaddr[strlen(zaddr)-1] = 0; + addr = zaddr+1; + } else addr = zaddr; + if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) + { + printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); + free(retstr), retstr = 0; + } + ptr->spent = (uint32_t)time(NULL); + free(zaddr); + break; + } + } + counter++; + } + } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); + } + } + break; + case 2: // z -> t + if ( Jumblr_numsecretaddrs > 0 ) + { + jumblr_opidsupdate(); + chosen_one = -1; + for (iter=0; iter<2; iter++) + { + counter = n = 0; + HASH_ITER(hh,Jumblrs,ptr,tmp) + { + //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); + if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) + { + if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) + { + if ( iter == 1 && counter == chosen_one ) + { + Jumblr_secretaddr(secretaddr); + if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) + { + printf("%s send z_to_t.(%s)\n",secretaddr,retstr); + free(retstr), retstr = 0; + } else printf("null return from jumblr_sendz_to_t\n"); + ptr->spent = (uint32_t)time(NULL); + break; + } + counter++; + } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); + } + n++; + } + if ( counter == 0 ) + break; + if ( iter == 0 ) + { + OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); + if ( chosen_one < 0 ) + chosen_one = -chosen_one; + chosen_one %= counter; + printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); + } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); + } + } + break; + } +} + std::lock_guard lock(komodo_mutex); + sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); + np = &sp->NPOINTS[sp->NUM_NPOINTS++]; + memset(np,0,sizeof(*np)); + np->nHeight = nHeight; + sp->NOTARIZED_HEIGHT = np->notarized_height = notarized_height; + sp->NOTARIZED_HASH = np->notarized_hash = notarized_hash; + sp->NOTARIZED_DESTTXID = np->notarized_desttxid = notarized_desttxid; + sp->MoM = np->MoM = MoM; + sp->MoMdepth = np->MoMdepth = MoMdepth; +} + +void komodo_init(int32_t height) +{ + static int didinit; uint256 zero; int32_t k,n; uint8_t pubkeys[64][33]; + if ( 0 && height != 0 ) + printf("komodo_init ht.%d didinit.%d\n",height,didinit); + memset(&zero,0,sizeof(zero)); + if ( didinit == 0 ) + { + decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + if ( height >= 0 ) + { + n = (int32_t)(sizeof(Notaries_genesis)/sizeof(*Notaries_genesis)); + for (k=0; k KMD_SEASON_HEIGHTS[i-1] ) - return(i+1); - } - return(0); -} - -int32_t getacseason(uint32_t timestamp) -{ - if ( timestamp <= KMD_SEASON_TIMESTAMPS[0] ) - return(1); - for (int32_t i = 1; i < NUM_KMD_SEASONS; i++) - { - if ( timestamp <= KMD_SEASON_TIMESTAMPS[i] && timestamp > KMD_SEASON_TIMESTAMPS[i-1] ) - return(i+1); - } - return(0); -} - -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) -{ - int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp; - static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33],didinit[NUM_KMD_SEASONS]; - - if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - timestamp = komodo_heightstamp(height); - else if ( ASSETCHAINS_SYMBOL[0] == 0 ) - timestamp = 0; - - // If this chain is not a staked chain, use the normal Komodo logic to determine notaries. This allows KMD to still sync and use its proper pubkeys for dPoW. - if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 ) - { - int32_t kmd_season = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - // This is KMD, use block heights to determine the KMD notary season.. - if ( height >= KOMODO_NOTARIES_HARDCODED ) - kmd_season = getkmdseason(height); - } - else - { - // This is a non LABS assetchain, use timestamp to detemine notary pubkeys. - kmd_season = getacseason(timestamp); - } - if ( kmd_season != 0 ) - { - if ( didinit[kmd_season-1] == 0 ) - { - for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - if ( Pubkeys == 0 ) - { - komodo_init(height); - //printf("Pubkeys.%p htind.%d vs max.%d\n",Pubkeys,htind,KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP); - } - { - std::lock_guard lock(komodo_mutex); - n = Pubkeys[htind].numnotaries; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"%s height.%d t.%u genesis.%d\n",ASSETCHAINS_SYMBOL,height,timestamp,n); - HASH_ITER(hh,Pubkeys[htind].Notaries,kp,tmp) - { - if ( kp->notaryid < n ) - { - mask |= (1LL << kp->notaryid); - memcpy(pubkeys[kp->notaryid],kp->pubkey,33); - } else printf("illegal notaryid.%d vs n.%d\n",kp->notaryid,n); - } - } - if ( (n < 64 && mask == ((1LL << n)-1)) || (n == 64 && mask == 0xffffffffffffffffLL) ) - return(n); - printf("error retrieving notaries ht.%d got mask.%llx for n.%d\n",height,(long long)mask,n); - return(-1); -} +int32_t getacseason(uint32_t timestamp); -int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp) -{ - int32_t i,n; uint8_t pubkeys[64][33]; - n = komodo_notaries(pubkeys,height,timestamp); - *numnotariesp = n; - for (i=0; i= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - numnotaries = Pubkeys[htind].numnotaries; - for (i=0; i (numnotaries >> 1) || (wt > 7 && (signedmask & 1) != 0) ) - return(1); - else return(0); -} +int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp); -void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num) -{ - static int32_t hwmheight; - int32_t k,i,htind,height; struct knotary_entry *kp; struct knotaries_entry N; - if ( Pubkeys == 0 ) - Pubkeys = (struct knotaries_entry *)calloc(1 + (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP),sizeof(*Pubkeys)); - memset(&N,0,sizeof(N)); - if ( origheight > 0 ) - { - height = (origheight + KOMODO_ELECTION_GAP/2); - height /= KOMODO_ELECTION_GAP; - height = ((height + 1) * KOMODO_ELECTION_GAP); - htind = (height / KOMODO_ELECTION_GAP); - if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - //printf("htind.%d activation %d from %d vs %d | hwmheight.%d %s\n",htind,height,origheight,(((origheight+KOMODO_ELECTION_GAP/2)/KOMODO_ELECTION_GAP)+1)*KOMODO_ELECTION_GAP,hwmheight,ASSETCHAINS_SYMBOL); - } else htind = 0; - std::lock_guard lock(komodo_mutex); - for (k=0; kpubkey,pubkeys[k],33); - kp->notaryid = k; - HASH_ADD_KEYPTR(hh,N.Notaries,kp->pubkey,33,kp); - if ( 0 && height > 10000 ) - { - for (i=0; i<33; i++) - printf("%02x",pubkeys[k][i]); - printf(" notarypubs.[%d] ht.%d active at %d\n",k,origheight,htind*KOMODO_ELECTION_GAP); - } - } - N.numnotaries = num; - for (i=htind; i hwmheight ) - hwmheight = origheight; -} +int32_t komodo_ratify_threshold(int32_t height,uint64_t signedmask); -int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp) -{ - // -1 if not notary, 0 if notary, 1 if special notary - struct knotary_entry *kp; int32_t numnotaries=0,htind,modval = -1; - *notaryidp = -1; - if ( height < 0 )//|| height >= KOMODO_MAXBLOCKS ) - { - printf("komodo_chosennotary ht.%d illegal\n",height); - return(-1); - } - if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 ) - { - if ( (*notaryidp= komodo_electednotary(&numnotaries,pubkey33,height,timestamp)) >= 0 && numnotaries != 0 ) - { - modval = ((height % numnotaries) == *notaryidp); - return(modval); - } - } - if ( height >= 250000 ) - return(-1); - if ( Pubkeys == 0 ) - komodo_init(0); - htind = height / KOMODO_ELECTION_GAP; - if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP ) - htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1; - { - std::lock_guard lock(komodo_mutex); - HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); - } - if ( kp != 0 ) - { - if ( (numnotaries= Pubkeys[htind].numnotaries) > 0 ) - { - *notaryidp = kp->notaryid; - modval = ((height % numnotaries) == kp->notaryid); - //printf("found notary.%d ht.%d modval.%d\n",kp->notaryid,height,modval); - } else printf("unexpected zero notaries at height.%d\n",height); - } //else printf("cant find kp at htind.%d ht.%d\n",htind,height); - //int32_t i; for (i=0; i<33; i++) - // printf("%02x",pubkey33[i]); - //printf(" ht.%d notary.%d special.%d htind.%d num.%d\n",height,*notaryidp,modval,htind,numnotaries); - return(modval); -} +void komodo_notarysinit(int32_t origheight,uint8_t pubkeys[64][33],int32_t num); -//struct komodo_state *komodo_stateptr(char *symbol,char *dest); +int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); -struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - for (i=sp->NUM_NPOINTS-1; i>=0; i--) - { - *idx = i; - np = &sp->NPOINTS[i]; - if ( np->MoMdepth != 0 && height > np->notarized_height-(np->MoMdepth&0xffff) && height <= np->notarized_height ) - return(np); - } - } - *idx = -1; - return(0); -} +struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx); -struct notarized_checkpoint *komodo_npptr(int32_t height) -{ - int idx; - return komodo_npptr_for_height(height, &idx); -} +struct notarized_checkpoint *komodo_npptr(int32_t height); -struct notarized_checkpoint *komodo_npptr_at(int idx) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - if (idx < sp->NUM_NPOINTS) - return &sp->NPOINTS[idx]; - return(0); -} +struct notarized_checkpoint *komodo_npptr_at(int idx); -int32_t komodo_prevMoMheight() -{ - static uint256 zero; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - for (i=sp->NUM_NPOINTS-1; i>=0; i--) - { - np = &sp->NPOINTS[i]; - if ( np->MoM != zero ) - return(np->notarized_height); - } - } - return(0); -} +int32_t komodo_prevMoMheight(); -int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - *prevMoMheightp = 0; - memset(hashp,0,sizeof(*hashp)); - memset(txidp,0,sizeof(*txidp)); - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - CBlockIndex *pindex; - if ( (pindex= komodo_blockindex(sp->NOTARIZED_HASH)) == 0 || pindex->GetHeight() < 0 ) - { - //fprintf(stderr,"found orphaned notarization at ht.%d pindex.%p\n",sp->NOTARIZED_HEIGHT,(void *)pindex); - memset(&sp->NOTARIZED_HASH,0,sizeof(sp->NOTARIZED_HASH)); - memset(&sp->NOTARIZED_DESTTXID,0,sizeof(sp->NOTARIZED_DESTTXID)); - sp->NOTARIZED_HEIGHT = 0; - } - else - { - *hashp = sp->NOTARIZED_HASH; - *txidp = sp->NOTARIZED_DESTTXID; - *prevMoMheightp = komodo_prevMoMheight(); - } - return(sp->NOTARIZED_HEIGHT); - } else return(0); -} +int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp); -int32_t komodo_dpowconfs(int32_t txheight,int32_t numconfs) -{ - static int32_t hadnotarization; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( KOMODO_DPOWCONFS != 0 && txheight > 0 && numconfs > 0 && (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - if ( sp->NOTARIZED_HEIGHT > 0 ) - { - hadnotarization = 1; - if ( txheight < sp->NOTARIZED_HEIGHT ) - return(numconfs); - else return(1); - } - else if ( hadnotarization != 0 ) - return(1); - } - return(numconfs); -} +int32_t komodo_dpowconfs(int32_t txheight,int32_t numconfs); -int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) -{ - struct notarized_checkpoint *np = 0; - if ( (np= komodo_npptr(height)) != 0 ) - { - *notarized_htp = np->notarized_height; - *MoMp = np->MoM; - *kmdtxidp = np->notarized_desttxid; - *MoMoMp = np->MoMoM; - *MoMoMoffsetp = np->MoMoMoffset; - *MoMoMdepthp = np->MoMoMdepth; - *kmdstartip = np->kmdstarti; - *kmdendip = np->kmdendi; - return(np->MoMdepth & 0xffff); - } - *notarized_htp = *MoMoMoffsetp = *MoMoMdepthp = *kmdstartip = *kmdendip = 0; - memset(MoMp,0,sizeof(*MoMp)); - memset(MoMoMp,0,sizeof(*MoMoMp)); - memset(kmdtxidp,0,sizeof(*kmdtxidp)); - return(0); -} +int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp) -{ - struct notarized_checkpoint *np = 0; int32_t i=0,flag = 0; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - if ( sp->NUM_NPOINTS > 0 ) - { - flag = 0; - if ( sp->last_NPOINTSi < sp->NUM_NPOINTS && sp->last_NPOINTSi > 0 ) - { - np = &sp->NPOINTS[sp->last_NPOINTSi-1]; - if ( np->nHeight < nHeight ) - { - for (i=sp->last_NPOINTSi; iNUM_NPOINTS; i++) - { - if ( sp->NPOINTS[i].nHeight >= nHeight ) - { - //printf("flag.1 i.%d np->ht %d [%d].ht %d >= nHeight.%d, last.%d num.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight,sp->last_NPOINTSi,sp->NUM_NPOINTS); - flag = 1; - break; - } - np = &sp->NPOINTS[i]; - sp->last_NPOINTSi = i; - } - } - } - if ( flag == 0 ) - { - np = 0; - for (i=0; iNUM_NPOINTS; i++) - { - if ( sp->NPOINTS[i].nHeight >= nHeight ) - { - //printf("i.%d np->ht %d [%d].ht %d >= nHeight.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight); - break; - } - np = &sp->NPOINTS[i]; - sp->last_NPOINTSi = i; - } - } - } - if ( np != 0 ) - { - //char str[65],str2[65]; printf("[%s] notarized_ht.%d\n",ASSETCHAINS_SYMBOL,np->notarized_height); - if ( np->nHeight >= nHeight || (i < sp->NUM_NPOINTS && np[1].nHeight < nHeight) ) - printf("warning: flag.%d i.%d np->ht %d [1].ht %d >= nHeight.%d\n",flag,i,np->nHeight,np[1].nHeight,nHeight); - *notarized_hashp = np->notarized_hash; - *notarized_desttxidp = np->notarized_desttxid; - return(np->notarized_height); - } - } - memset(notarized_hashp,0,sizeof(*notarized_hashp)); - memset(notarized_desttxidp,0,sizeof(*notarized_desttxidp)); - return(0); -} +int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); -void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_desttxid,uint256 MoM,int32_t MoMdepth) -{ - struct notarized_checkpoint *np; - if ( notarized_height >= nHeight ) - { - fprintf(stderr,"komodo_notarized_update REJECT notarized_height %d > %d nHeight\n",notarized_height,nHeight); - return; - } - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); - std::lock_guard lock(komodo_mutex); - sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); - np = &sp->NPOINTS[sp->NUM_NPOINTS++]; - memset(np,0,sizeof(*np)); - np->nHeight = nHeight; - sp->NOTARIZED_HEIGHT = np->notarized_height = notarized_height; - sp->NOTARIZED_HASH = np->notarized_hash = notarized_hash; - sp->NOTARIZED_DESTTXID = np->notarized_desttxid = notarized_desttxid; - sp->MoM = np->MoM = MoM; - sp->MoMdepth = np->MoMdepth = MoMdepth; -} +void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t notarized_height,uint256 notarized_hash,uint256 notarized_desttxid,uint256 MoM,int32_t MoMdepth); -void komodo_init(int32_t height) -{ - static int didinit; uint256 zero; int32_t k,n; uint8_t pubkeys[64][33]; - if ( 0 && height != 0 ) - printf("komodo_init ht.%d didinit.%d\n",height,didinit); - memset(&zero,0,sizeof(zero)); - if ( didinit == 0 ) - { - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); - if ( height >= 0 ) - { - n = (int32_t)(sizeof(Notaries_genesis)/sizeof(*Notaries_genesis)); - for (k=0; k= 32 ) + return(0); + if ( baseid < 10 ) + val *= 4; + mult = MINDENOMS[baseid] / MIND; + return(mult * val); +} + +uint64_t komodo_paxvol(uint64_t volume,uint64_t price) +{ + if ( volume < 10000000000 ) + return((volume * price) / 1000000000); + else if ( volume < (uint64_t)10 * 10000000000 ) + return((volume * (price / 10)) / 100000000); + else if ( volume < (uint64_t)100 * 10000000000 ) + return(((volume / 10) * (price / 10)) / 10000000); + else if ( volume < (uint64_t)1000 * 10000000000 ) + return(((volume / 10) * (price / 100)) / 1000000); + else if ( volume < (uint64_t)10000 * 10000000000 ) + return(((volume / 100) * (price / 100)) / 100000); + else if ( volume < (uint64_t)100000 * 10000000000 ) + return(((volume / 100) * (price / 1000)) / 10000); + else if ( volume < (uint64_t)1000000 * 10000000000 ) + return(((volume / 1000) * (price / 1000)) / 1000); + else if ( volume < (uint64_t)10000000 * 10000000000 ) + return(((volume / 1000) * (price / 10000)) / 100); + else return(((volume / 10000) * (price / 10000)) / 10); +} + +void pax_rank(uint64_t *ranked,uint32_t *pvals) +{ + int32_t i; uint64_t vals[32],sum = 0; + for (i=0; i<32; i++) + { + vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]); + sum += vals[i]; + } + for (i=0; i<32; i++) + { + ranked[i] = (vals[i] * 1000000000) / sum; + //printf("%.6f ",(double)ranked[i]/1000000000.); + } + //printf("sum %llu\n",(long long)sum); +}; + +#define BTCFACTOR_HEIGHT 466266 + +double PAX_BTCUSD(int32_t height,uint32_t btcusd) +{ + double btcfactor,BTCUSD; + if ( height >= BTCFACTOR_HEIGHT ) + btcfactor = 100000.; + else btcfactor = 1000.; + BTCUSD = ((double)btcusd / (1000000000. / btcfactor)); + if ( height >= BTCFACTOR_HEIGHT && height < 500000 && BTCUSD > 20000 && btcfactor == 100000. ) + BTCUSD /= 100; + return(BTCUSD); +} + +int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals) +{ + uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0; + if ( data[0] == 'P' && data[5] == 35 ) + data++; + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); + if ( n != 35 ) + { + printf("dpow_readprices illegal n.%d\n",n); + return(-1); + } + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 + len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); + *KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.)); + *BTCUSDp = PAX_BTCUSD(height,btcusd); + *CNYUSDp = ((double)cnyusd / 1000000000.); + for (i=nonz=0; i sizeof(crc32) ) + { + if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize ) + { + len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32); + check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); + if ( check == crc32 ) + { + double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128]; + if ( dpow_readprices(height,&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals) > 0 ) + { + if ( 0 && lastcrc != crc32 ) + { + for (i=0; i<32; i++) + printf("%u ",pvals[i]); + printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0); + } + if ( timestamp > time(NULL)-600 ) + { + n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); + if ( 0 && lastcrc != crc32 ) + { + for (i=0; i maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data)); + fclose(fp); + } //else printf("couldnt open %s\n",fname); + return(n); +} + +int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp) +{ + if ( rwflag != 0 ) + { + memset(pubkey33,0,33); + pubkey33[0] = 0x02 | (*shortflagp != 0); + memcpy(&pubkey33[1],fiat,3); + iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); + pubkey33[12] = *addrtypep; + memcpy(&pubkey33[13],rmd160,20); + } + else + { + *shortflagp = (pubkey33[0] == 0x03); + memcpy(fiat,&pubkey33[1],3); + fiat[3] = 0; + iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); + if ( *shortflagp != 0 ) + *fiatoshisp = -(*fiatoshisp); + *addrtypep = pubkey33[12]; + memcpy(rmd160,&pubkey33[13],20); + } + return(33); +} + +double PAX_val(uint32_t pval,int32_t baseid) +{ + //printf("PAX_val baseid.%d pval.%u\n",baseid,pval); + if ( baseid >= 0 && baseid < MAX_CURRENCIES ) + return(((double)pval / 1000000000.) / MINDENOMS[baseid]); + return(0.); +} + +void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals) +{ + int32_t i,nonz; uint32_t kmdbtc,btcusd,cnyusd; double KMDBTC,BTCUSD,CNYUSD; + if ( numpvals >= 35 ) + { + for (nonz=i=0; i<32; i++) + { + if ( pvals[i] != 0 ) + nonz++; + //printf("%u ",pvals[i]); + } + if ( nonz == 32 ) + { + kmdbtc = pvals[i++]; + btcusd = pvals[i++]; + cnyusd = pvals[i++]; + KMDBTC = ((double)kmdbtc / (1000000000. * 1000.)); + BTCUSD = PAX_BTCUSD(height,btcusd); + CNYUSD = ((double)cnyusd / 1000000000.); + std::lock_guard lock(komodo_mutex); + PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36); + PVALS[36 * NUM_PRICES] = height; + memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35); + NUM_PRICES++; + } + } +} + +uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed) +{ + int32_t i,j,k,ind,zeroes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0; + for (sum=i=zeroes=nonz=0; i> 2) ) + return(0); + sum /= nonz; + lastprice = sum; + for (i=0; i (numvotes >> 1) ) + break; + } + } + } + } + if ( wt > (numvotes >> 1) ) + { + ind = i; + for (densum=sum=j=0; j KOMODO_PAXMAX ) + { + printf("paxcalc overflow %.8f\n",dstr(basevolume)); + return(0); + } + if ( (pvalb= pvals[baseid]) != 0 ) + { + if ( relid == MAX_CURRENCIES ) + { + if ( height < 236000 ) + { + if ( kmdbtc == 0 ) + kmdbtc = pvals[MAX_CURRENCIES]; + if ( btcusd == 0 ) + btcusd = pvals[MAX_CURRENCIES + 1]; + } + else + { + if ( (kmdbtc= pvals[MAX_CURRENCIES]) == 0 ) + kmdbtc = refkmdbtc; + if ( (btcusd= pvals[MAX_CURRENCIES + 1]) == 0 ) + btcusd = refbtcusd; + } + if ( kmdbtc < 25000000 ) + kmdbtc = 25000000; + if ( pvals[USD] != 0 && kmdbtc != 0 && btcusd != 0 ) + { + baseusd = (((uint64_t)pvalb * 1000000000) / pvals[USD]); + usdvol = komodo_paxvol(basevolume,baseusd); + usdkmd = ((uint64_t)kmdbtc * 1000000000) / btcusd; + if ( height >= 236000-10 ) + { + BTCUSD = PAX_BTCUSD(height,btcusd); + if ( height < BTCFACTOR_HEIGHT || (height < 500000 && BTCUSD > 20000) ) + usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; + else usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; + ///if ( height >= BTCFACTOR_HEIGHT && BTCUSD >= 43 ) + // usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; + //else usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; + price = ((uint64_t)10000000000 * MINDENOMS[USD] / MINDENOMS[baseid]) / komodo_paxvol(usdvol,usdkmd); + //fprintf(stderr,"ht.%d %.3f kmdbtc.%llu btcusd.%llu base -> USD %llu, usdkmd %llu usdvol %llu -> %llu\n",height,BTCUSD,(long long)kmdbtc,(long long)btcusd,(long long)baseusd,(long long)usdkmd,(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); + //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)),(long long)price); + //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); + } else price = (MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)); + return(price); + } //else printf("zero val in KMD conv %llu %llu %llu\n",(long long)pvals[USD],(long long)kmdbtc,(long long)btcusd); + } + else if ( baseid == relid ) + { + if ( baseid != MAX_CURRENCIES ) + { + pax_rank(ranked,pvals); + //printf("%s M1 percentage %.8f\n",CURRENCIES[baseid],dstr(10 * ranked[baseid])); + return(10 * ranked[baseid]); // scaled percentage of M1 total + } else return(basevolume); + } + else if ( (pvalr= pvals[relid]) != 0 ) + { + baserel = ((uint64_t)pvalb * 1000000000) / pvalr; + //printf("baserel.%lld %lld %lld %.8f %.8f\n",(long long)baserel,(long long)MINDENOMS[baseid],(long long)MINDENOMS[relid],dstr(MINDENOMS[baseid]/MINDENOMS[relid]),dstr(MINDENOMS[relid]/MINDENOMS[baseid])); + if ( MINDENOMS[baseid] > MINDENOMS[relid] ) + basevolume /= (MINDENOMS[baseid] / MINDENOMS[relid]); + else if ( MINDENOMS[baseid] < MINDENOMS[relid] ) + basevolume *= (MINDENOMS[relid] / MINDENOMS[baseid]); + return(komodo_paxvol(basevolume,baserel)); + } + else printf("null pval for %s\n",CURRENCIES[relid]); + } else printf("null pval for %s\n",CURRENCIES[baseid]); + return(0); +} + +uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,char *base,char *rel,uint64_t basevolume,uint64_t kmdbtc,uint64_t btcusd) +{ + int32_t baseid=-1,relid=-1,i; uint32_t *ptr,*pvals; + if ( height > 10 ) + height -= 10; + if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) + { + for (i=NUM_PRICES-1; i>=0; i--) + { + ptr = &PVALS[36 * i]; + if ( *ptr < height ) + { + pvals = &ptr[1]; + if ( kmdbtcp != 0 && btcusdp != 0 ) + { + *kmdbtcp = pvals[MAX_CURRENCIES] / 539; + *btcusdp = pvals[MAX_CURRENCIES + 1] / 539; + } + if ( kmdbtc != 0 && btcusd != 0 ) + return(komodo_paxcalc(height,pvals,baseid,relid,basevolume,kmdbtc,btcusd)); + else return(0); + } + } + } //else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); + return(0); +} + +int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height) +{ + static uint64_t *KMDBTCS,*BTCUSDS; static int32_t maxheight = 0; int32_t incr = 10000; + if ( height >= maxheight ) + { + //printf("height.%d maxheight.%d incr.%d\n",height,maxheight,incr); + if ( height >= maxheight+incr ) + incr = (height - (maxheight+incr) + 1000); + KMDBTCS = (uint64_t *)realloc(KMDBTCS,((incr + maxheight) * sizeof(*KMDBTCS))); + memset(&KMDBTCS[maxheight],0,(incr * sizeof(*KMDBTCS))); + BTCUSDS = (uint64_t *)realloc(BTCUSDS,((incr + maxheight) * sizeof(*BTCUSDS))); + memset(&BTCUSDS[maxheight],0,(incr * sizeof(*BTCUSDS))); + maxheight += incr; + } + if ( rwflag == 0 ) + { + *kmdbtcp = KMDBTCS[height]; + *btcusdp = BTCUSDS[height]; + } + else + { + KMDBTCS[height] = *kmdbtcp; + BTCUSDS[height] = *btcusdp; + } + if ( *kmdbtcp != 0 && *btcusdp != 0 ) + return(0); + else return(-1); +} + +uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) +{ + int32_t i,j,k,ind,zeroes,numvotes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0,votes[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],btcusds[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtcs[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtc,btcusd; + if ( basevolume > KOMODO_PAXMAX ) + { + printf("komodo_paxprice overflow %.8f\n",dstr(basevolume)); + return(0); + } + if ( strcmp(base,"KMD") == 0 || strcmp(base,"kmd") == 0 ) + { + printf("kmd cannot be base currency\n"); + return(0); + } + numvotes = (int32_t)(sizeof(Peggy_inds)/sizeof(*Peggy_inds)); + memset(votes,0,sizeof(votes)); + //if ( komodo_kmdbtcusd(0,&kmdbtc,&btcusd,height) < 0 ) crashes when via passthru GUI use + { + memset(btcusds,0,sizeof(btcusds)); + memset(kmdbtcs,0,sizeof(kmdbtcs)); + for (i=0; i> 1) ) + { + return(0); + } + return(komodo_paxcorrelation(votes,numvotes,seed) * basevolume / 100000); +} + +uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) +{ + uint64_t baseusd,basekmd,usdkmd; int32_t baseid = komodo_baseid(base); + if ( height >= 236000 && strcmp(rel,"kmd") == 0 ) + { + usdkmd = _komodo_paxpriceB(seed,height,(char *)"USD",(char *)"KMD",SATOSHIDEN); + if ( strcmp("usd",base) == 0 ) + return(komodo_paxvol(basevolume,usdkmd) * 10); + baseusd = _komodo_paxpriceB(seed,height,base,(char *)"USD",SATOSHIDEN); + basekmd = (komodo_paxvol(basevolume,baseusd) * usdkmd) / 10000000; + //if ( strcmp("KMD",base) == 0 ) + // printf("baseusd.%llu usdkmd.%llu %llu\n",(long long)baseusd,(long long)usdkmd,(long long)basekmd); + return(basekmd); + } else return(_komodo_paxpriceB(seed,height,base,rel,basevolume)); +} + +uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume) +{ + int32_t i,nonz=0; int64_t diff; uint64_t price,seed,sum = 0; + if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && height > chainActive.LastTip()->GetHeight() ) + { + if ( height < 100000000 ) + { + static uint32_t counter; + if ( counter++ < 3 ) + printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.LastTip()->GetHeight()); + } + return(0); + } + *seedp = komodo_seed(height); + { + std::lock_guard lock(komodo_mutex); + for (i=0; i<17; i++) + { + if ( (price= komodo_paxpriceB(*seedp,height-i,base,rel,basevolume)) != 0 ) + { + sum += price; + nonz++; + if ( 0 && i == 1 && nonz == 2 ) + { + diff = (((int64_t)price - (sum >> 1)) * 10000); + if ( diff < 0 ) + diff = -diff; + diff /= price; + printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>1),(long long)(((int64_t)price - (sum >> 1)) * 10000),(long long)diff); + if ( diff < 33 ) + break; + } + else if ( 0 && i == 3 && nonz == 4 ) + { + diff = (((int64_t)price - (sum >> 2)) * 10000); + if ( diff < 0 ) + diff = -diff; + diff /= price; + printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>2),(long long) (((int64_t)price - (sum >> 2)) * 10000),(long long)diff); + if ( diff < 20 ) + break; + } + } + if ( height < 165000 || height > 236000 ) + break; + } + } + if ( nonz != 0 ) + sum /= nonz; + //printf("-> %lld %s/%s i.%d ht.%d\n",(long long)sum,base,rel,i,height); + return(sum); +} + +int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel) +{ + int32_t baseid=-1,relid=-1,i,num = 0; uint32_t *ptr; + if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) + { + for (i=NUM_PRICES-1; i>=0; i--) + { + ptr = &PVALS[36 * i]; + heights[num] = *ptr; + prices[num] = komodo_paxcalc(*ptr,&ptr[1],baseid,relid,COIN,0,0); + num++; + if ( num >= max ) + return(num); + } + } + return(num); +} + +void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen) +{ + double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128]; uint256 zero; + numpvals = dpow_readprices(height,pricefeed,×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals); + memset(&zero,0,sizeof(zero)); + komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals,0,0,0,0,0,0,zero,0); + if ( 0 ) + { + int32_t i; + for (i=0; i KMD %.8f seed.%llx\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN,(long long)*seedp); + if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) + { + PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); + bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33); + } + return(komodoshis); +} diff --git a/src/komodo_pax.h b/src/komodo_pax.h index aadebc43bb0..e67d6922da9 100644 --- a/src/komodo_pax.h +++ b/src/komodo_pax.h @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once #include "komodo_defs.h" #define USD 0 @@ -130,611 +130,40 @@ uint64_t peggy_smooth_coeffs[sizeof(Peggy_inds)/sizeof(*Peggy_inds)] = // numpri 1, 1, 1, 1, 1, 1, 0, 0, // isum 100000000000 }; -uint64_t komodo_maxallowed(int32_t baseid) -{ - uint64_t mult,val = COIN * (uint64_t)10000; - if ( baseid < 0 || baseid >= 32 ) - return(0); - if ( baseid < 10 ) - val *= 4; - mult = MINDENOMS[baseid] / MIND; - return(mult * val); -} +uint64_t komodo_maxallowed(int32_t baseid); -uint64_t komodo_paxvol(uint64_t volume,uint64_t price) -{ - if ( volume < 10000000000 ) - return((volume * price) / 1000000000); - else if ( volume < (uint64_t)10 * 10000000000 ) - return((volume * (price / 10)) / 100000000); - else if ( volume < (uint64_t)100 * 10000000000 ) - return(((volume / 10) * (price / 10)) / 10000000); - else if ( volume < (uint64_t)1000 * 10000000000 ) - return(((volume / 10) * (price / 100)) / 1000000); - else if ( volume < (uint64_t)10000 * 10000000000 ) - return(((volume / 100) * (price / 100)) / 100000); - else if ( volume < (uint64_t)100000 * 10000000000 ) - return(((volume / 100) * (price / 1000)) / 10000); - else if ( volume < (uint64_t)1000000 * 10000000000 ) - return(((volume / 1000) * (price / 1000)) / 1000); - else if ( volume < (uint64_t)10000000 * 10000000000 ) - return(((volume / 1000) * (price / 10000)) / 100); - else return(((volume / 10000) * (price / 10000)) / 10); -} +uint64_t komodo_paxvol(uint64_t volume,uint64_t price); -void pax_rank(uint64_t *ranked,uint32_t *pvals) -{ - int32_t i; uint64_t vals[32],sum = 0; - for (i=0; i<32; i++) - { - vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]); - sum += vals[i]; - } - for (i=0; i<32; i++) - { - ranked[i] = (vals[i] * 1000000000) / sum; - //printf("%.6f ",(double)ranked[i]/1000000000.); - } - //printf("sum %llu\n",(long long)sum); -}; +void pax_rank(uint64_t *ranked,uint32_t *pvals); -#define BTCFACTOR_HEIGHT 466266 +double PAX_BTCUSD(int32_t height,uint32_t btcusd); -double PAX_BTCUSD(int32_t height,uint32_t btcusd) -{ - double btcfactor,BTCUSD; - if ( height >= BTCFACTOR_HEIGHT ) - btcfactor = 100000.; - else btcfactor = 1000.; - BTCUSD = ((double)btcusd / (1000000000. / btcfactor)); - if ( height >= BTCFACTOR_HEIGHT && height < 500000 && BTCUSD > 20000 && btcfactor == 100000. ) - BTCUSD /= 100; - return(BTCUSD); -} +int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals); -int32_t dpow_readprices(int32_t height,uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals) -{ - uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0; - if ( data[0] == 'P' && data[5] == 35 ) - data++; - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); - if ( n != 35 ) - { - printf("dpow_readprices illegal n.%d\n",n); - return(-1); - } - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 - len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); - *KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.)); - *BTCUSDp = PAX_BTCUSD(height,btcusd); - *CNYUSDp = ((double)cnyusd / 1000000000.); - for (i=nonz=0; i sizeof(crc32) ) - { - if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize ) - { - len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32); - check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); - if ( check == crc32 ) - { - double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128]; - if ( dpow_readprices(height,&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals) > 0 ) - { - if ( 0 && lastcrc != crc32 ) - { - for (i=0; i<32; i++) - printf("%u ",pvals[i]); - printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0); - } - if ( timestamp > time(NULL)-600 ) - { - n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); - if ( 0 && lastcrc != crc32 ) - { - for (i=0; i maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data)); - fclose(fp); - } //else printf("couldnt open %s\n",fname); - return(n); -} +int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp); -/*uint32_t PAX_val32(double val) - { - uint32_t val32 = 0; struct price_resolution price; - if ( (price.Pval= val*1000000000) != 0 ) - { - if ( price.Pval > 0xffffffff ) - printf("Pval overflow error %lld\n",(long long)price.Pval); - else val32 = (uint32_t)price.Pval; - } - return(val32); - }*/ +double PAX_val(uint32_t pval,int32_t baseid); -int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp) -{ - if ( rwflag != 0 ) - { - memset(pubkey33,0,33); - pubkey33[0] = 0x02 | (*shortflagp != 0); - memcpy(&pubkey33[1],fiat,3); - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); - pubkey33[12] = *addrtypep; - memcpy(&pubkey33[13],rmd160,20); - } - else - { - *shortflagp = (pubkey33[0] == 0x03); - memcpy(fiat,&pubkey33[1],3); - fiat[3] = 0; - iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); - if ( *shortflagp != 0 ) - *fiatoshisp = -(*fiatoshisp); - *addrtypep = pubkey33[12]; - memcpy(rmd160,&pubkey33[13],20); - } - return(33); -} +void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals); -double PAX_val(uint32_t pval,int32_t baseid) -{ - //printf("PAX_val baseid.%d pval.%u\n",baseid,pval); - if ( baseid >= 0 && baseid < MAX_CURRENCIES ) - return(((double)pval / 1000000000.) / MINDENOMS[baseid]); - return(0.); -} +uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed); -void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals) -{ - int32_t i,nonz; uint32_t kmdbtc,btcusd,cnyusd; double KMDBTC,BTCUSD,CNYUSD; - if ( numpvals >= 35 ) - { - for (nonz=i=0; i<32; i++) - { - if ( pvals[i] != 0 ) - nonz++; - //printf("%u ",pvals[i]); - } - if ( nonz == 32 ) - { - kmdbtc = pvals[i++]; - btcusd = pvals[i++]; - cnyusd = pvals[i++]; - KMDBTC = ((double)kmdbtc / (1000000000. * 1000.)); - BTCUSD = PAX_BTCUSD(height,btcusd); - CNYUSD = ((double)cnyusd / 1000000000.); - std::lock_guard lock(komodo_mutex); - PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36); - PVALS[36 * NUM_PRICES] = height; - memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35); - NUM_PRICES++; - if ( 0 ) - printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d (%llu %llu %llu)\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES,(long long)kmdbtc,(long long)btcusd,(long long)cnyusd); - } - } -} +uint64_t komodo_paxcalc(int32_t height,uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t basevolume,uint64_t refkmdbtc,uint64_t refbtcusd); -uint64_t komodo_paxcorrelation(uint64_t *votes,int32_t numvotes,uint64_t seed) -{ - int32_t i,j,k,ind,zeroes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0; - for (sum=i=zeroes=nonz=0; i> 2) ) - return(0); - sum /= nonz; - lastprice = sum; - for (i=0; i (numvotes >> 1) ) - break; - } - } - } - } - if ( wt > (numvotes >> 1) ) - { - ind = i; - for (densum=sum=j=0; j KOMODO_PAXMAX ) - { - printf("paxcalc overflow %.8f\n",dstr(basevolume)); - return(0); - } - if ( (pvalb= pvals[baseid]) != 0 ) - { - if ( relid == MAX_CURRENCIES ) - { - if ( height < 236000 ) - { - if ( kmdbtc == 0 ) - kmdbtc = pvals[MAX_CURRENCIES]; - if ( btcusd == 0 ) - btcusd = pvals[MAX_CURRENCIES + 1]; - } - else - { - if ( (kmdbtc= pvals[MAX_CURRENCIES]) == 0 ) - kmdbtc = refkmdbtc; - if ( (btcusd= pvals[MAX_CURRENCIES + 1]) == 0 ) - btcusd = refbtcusd; - } - if ( kmdbtc < 25000000 ) - kmdbtc = 25000000; - if ( pvals[USD] != 0 && kmdbtc != 0 && btcusd != 0 ) - { - baseusd = (((uint64_t)pvalb * 1000000000) / pvals[USD]); - usdvol = komodo_paxvol(basevolume,baseusd); - usdkmd = ((uint64_t)kmdbtc * 1000000000) / btcusd; - if ( height >= 236000-10 ) - { - BTCUSD = PAX_BTCUSD(height,btcusd); - if ( height < BTCFACTOR_HEIGHT || (height < 500000 && BTCUSD > 20000) ) - usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; - else usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; - ///if ( height >= BTCFACTOR_HEIGHT && BTCUSD >= 43 ) - // usdkmd = ((uint64_t)kmdbtc * btcusd) / 10000000; - //else usdkmd = ((uint64_t)kmdbtc * btcusd) / 1000000000; - price = ((uint64_t)10000000000 * MINDENOMS[USD] / MINDENOMS[baseid]) / komodo_paxvol(usdvol,usdkmd); - //fprintf(stderr,"ht.%d %.3f kmdbtc.%llu btcusd.%llu base -> USD %llu, usdkmd %llu usdvol %llu -> %llu\n",height,BTCUSD,(long long)kmdbtc,(long long)btcusd,(long long)baseusd,(long long)usdkmd,(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); - //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)),(long long)price); - //fprintf(stderr,"usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,(long long)(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100))); - } else price = (MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd) / (MINDENOMS[baseid]/100)); - return(price); - } //else printf("zero val in KMD conv %llu %llu %llu\n",(long long)pvals[USD],(long long)kmdbtc,(long long)btcusd); - } - else if ( baseid == relid ) - { - if ( baseid != MAX_CURRENCIES ) - { - pax_rank(ranked,pvals); - //printf("%s M1 percentage %.8f\n",CURRENCIES[baseid],dstr(10 * ranked[baseid])); - return(10 * ranked[baseid]); // scaled percentage of M1 total - } else return(basevolume); - } - else if ( (pvalr= pvals[relid]) != 0 ) - { - baserel = ((uint64_t)pvalb * 1000000000) / pvalr; - //printf("baserel.%lld %lld %lld %.8f %.8f\n",(long long)baserel,(long long)MINDENOMS[baseid],(long long)MINDENOMS[relid],dstr(MINDENOMS[baseid]/MINDENOMS[relid]),dstr(MINDENOMS[relid]/MINDENOMS[baseid])); - if ( MINDENOMS[baseid] > MINDENOMS[relid] ) - basevolume /= (MINDENOMS[baseid] / MINDENOMS[relid]); - else if ( MINDENOMS[baseid] < MINDENOMS[relid] ) - basevolume *= (MINDENOMS[relid] / MINDENOMS[baseid]); - return(komodo_paxvol(basevolume,baserel)); - } - else printf("null pval for %s\n",CURRENCIES[relid]); - } else printf("null pval for %s\n",CURRENCIES[baseid]); - return(0); -} +int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height); -uint64_t _komodo_paxprice(uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height,char *base,char *rel,uint64_t basevolume,uint64_t kmdbtc,uint64_t btcusd) -{ - int32_t baseid=-1,relid=-1,i; uint32_t *ptr,*pvals; - if ( height > 10 ) - height -= 10; - if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) - { - for (i=NUM_PRICES-1; i>=0; i--) - { - ptr = &PVALS[36 * i]; - if ( *ptr < height ) - { - pvals = &ptr[1]; - if ( kmdbtcp != 0 && btcusdp != 0 ) - { - *kmdbtcp = pvals[MAX_CURRENCIES] / 539; - *btcusdp = pvals[MAX_CURRENCIES + 1] / 539; - } - if ( kmdbtc != 0 && btcusd != 0 ) - return(komodo_paxcalc(height,pvals,baseid,relid,basevolume,kmdbtc,btcusd)); - else return(0); - } - } - } //else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); - return(0); -} - -int32_t komodo_kmdbtcusd(int32_t rwflag,uint64_t *kmdbtcp,uint64_t *btcusdp,int32_t height) -{ - static uint64_t *KMDBTCS,*BTCUSDS; static int32_t maxheight = 0; int32_t incr = 10000; - if ( height >= maxheight ) - { - //printf("height.%d maxheight.%d incr.%d\n",height,maxheight,incr); - if ( height >= maxheight+incr ) - incr = (height - (maxheight+incr) + 1000); - KMDBTCS = (uint64_t *)realloc(KMDBTCS,((incr + maxheight) * sizeof(*KMDBTCS))); - memset(&KMDBTCS[maxheight],0,(incr * sizeof(*KMDBTCS))); - BTCUSDS = (uint64_t *)realloc(BTCUSDS,((incr + maxheight) * sizeof(*BTCUSDS))); - memset(&BTCUSDS[maxheight],0,(incr * sizeof(*BTCUSDS))); - maxheight += incr; - } - if ( rwflag == 0 ) - { - *kmdbtcp = KMDBTCS[height]; - *btcusdp = BTCUSDS[height]; - } - else - { - KMDBTCS[height] = *kmdbtcp; - BTCUSDS[height] = *btcusdp; - } - if ( *kmdbtcp != 0 && *btcusdp != 0 ) - return(0); - else return(-1); -} - -uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - int32_t i,j,k,ind,zeroes,numvotes,wt,nonz; int64_t delta; uint64_t lastprice,tolerance,den,densum,sum=0,votes[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],btcusds[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtcs[sizeof(Peggy_inds)/sizeof(*Peggy_inds)],kmdbtc,btcusd; - if ( basevolume > KOMODO_PAXMAX ) - { - printf("komodo_paxprice overflow %.8f\n",dstr(basevolume)); - return(0); - } - if ( strcmp(base,"KMD") == 0 || strcmp(base,"kmd") == 0 ) - { - printf("kmd cannot be base currency\n"); - return(0); - } - numvotes = (int32_t)(sizeof(Peggy_inds)/sizeof(*Peggy_inds)); - memset(votes,0,sizeof(votes)); - //if ( komodo_kmdbtcusd(0,&kmdbtc,&btcusd,height) < 0 ) crashes when via passthru GUI use - { - memset(btcusds,0,sizeof(btcusds)); - memset(kmdbtcs,0,sizeof(kmdbtcs)); - for (i=0; i> 1) ) - { - return(0); - } - return(komodo_paxcorrelation(votes,numvotes,seed) * basevolume / 100000); -} - -uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - uint64_t baseusd,basekmd,usdkmd; int32_t baseid = komodo_baseid(base); - if ( height >= 236000 && strcmp(rel,"kmd") == 0 ) - { - usdkmd = _komodo_paxpriceB(seed,height,(char *)"USD",(char *)"KMD",SATOSHIDEN); - if ( strcmp("usd",base) == 0 ) - return(komodo_paxvol(basevolume,usdkmd) * 10); - baseusd = _komodo_paxpriceB(seed,height,base,(char *)"USD",SATOSHIDEN); - basekmd = (komodo_paxvol(basevolume,baseusd) * usdkmd) / 10000000; - //if ( strcmp("KMD",base) == 0 ) - // printf("baseusd.%llu usdkmd.%llu %llu\n",(long long)baseusd,(long long)usdkmd,(long long)basekmd); - return(basekmd); - } else return(_komodo_paxpriceB(seed,height,base,rel,basevolume)); -} +uint64_t _komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume); -/*uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - uint64_t baseusd,basekmd,usdkmd; int32_t baseid = komodo_baseid(base); - //if ( strcmp(rel,"KMD") != 0 || baseid < 0 || MINDENOMS[baseid] == MINDENOMS[USD] ) - // return(_komodo_paxpriceB(seed,height,base,rel,basevolume)); - //else - { - baseusd = _komodo_paxpriceB(seed,height,base,(char *)"USD",SATOSHIDEN); - usdkmd = _komodo_paxpriceB(seed,height,(char *)"USD",(char *)"KMD",SATOSHIDEN); - basekmd = (komodo_paxvol(basevolume,baseusd) * usdkmd) / 10000000; - if ( strcmp("KMD",base) == 0 ) - printf("baseusd.%llu usdkmd.%llu %llu\n",(long long)baseusd,(long long)usdkmd,(long long)basekmd); - return(basekmd); - } -}*/ +uint64_t komodo_paxpriceB(uint64_t seed,int32_t height,char *base,char *rel,uint64_t basevolume); -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume) -{ - int32_t i,nonz=0; int64_t diff; uint64_t price,seed,sum = 0; - if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && height > chainActive.LastTip()->GetHeight() ) - { - if ( height < 100000000 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - printf("komodo_paxprice height.%d vs tip.%d\n",height,chainActive.LastTip()->GetHeight()); - } - return(0); - } - *seedp = komodo_seed(height); - std::lock_guard lock(komodo_mutex); - for (i=0; i<17; i++) - { - if ( (price= komodo_paxpriceB(*seedp,height-i,base,rel,basevolume)) != 0 ) - { - sum += price; - nonz++; - if ( 0 && i == 1 && nonz == 2 ) - { - diff = (((int64_t)price - (sum >> 1)) * 10000); - if ( diff < 0 ) - diff = -diff; - diff /= price; - printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>1),(long long)(((int64_t)price - (sum >> 1)) * 10000),(long long)diff); - if ( diff < 33 ) - break; - } - else if ( 0 && i == 3 && nonz == 4 ) - { - diff = (((int64_t)price - (sum >> 2)) * 10000); - if ( diff < 0 ) - diff = -diff; - diff /= price; - printf("(%llu %llu %lld).%lld ",(long long)price,(long long)(sum>>2),(long long) (((int64_t)price - (sum >> 2)) * 10000),(long long)diff); - if ( diff < 20 ) - break; - } - } - if ( height < 165000 || height > 236000 ) - break; - } - if ( nonz != 0 ) - sum /= nonz; - //printf("-> %lld %s/%s i.%d ht.%d\n",(long long)sum,base,rel,i,height); - return(sum); -} +uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel) -{ - int32_t baseid=-1,relid=-1,i,num = 0; uint32_t *ptr; - if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) - { - for (i=NUM_PRICES-1; i>=0; i--) - { - ptr = &PVALS[36 * i]; - heights[num] = *ptr; - prices[num] = komodo_paxcalc(*ptr,&ptr[1],baseid,relid,COIN,0,0); - num++; - if ( num >= max ) - return(num); - } - } - return(num); -} +int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); -void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen) -{ - double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128]; uint256 zero; - numpvals = dpow_readprices(height,pricefeed,×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals); - memset(&zero,0,sizeof(zero)); - komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals,0,0,0,0,0,0,zero,0); - if ( 0 ) - { - int32_t i; - for (i=0; i KMD %.8f seed.%llx\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN,(long long)*seedp); - if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) - { - PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); - bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33); - } - return(komodoshis); -} +uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *origbase,int64_t fiatoshis); diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp new file mode 100644 index 00000000000..33243aa2689 --- /dev/null +++ b/src/komodo_utils.cpp @@ -0,0 +1,1864 @@ +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_utils.h" + +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) +{ + struct sha256_vstate md; + sha256_vinit(&md); + sha256_vprocess(&md,src,len); + sha256_vdone(&md,hash); +} + +bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) +{ + bits256 hash,hash2; int32_t i; + vcalc_sha256(0,hash.bytes,data,datalen); + vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash)); + for (i=0; istate[0] = 0x67452301UL; + md->state[1] = 0xefcdab89UL; + md->state[2] = 0x98badcfeUL; + md->state[3] = 0x10325476UL; + md->state[4] = 0xc3d2e1f0UL; + md->curlen = 0; + md->length = 0; + return 0; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return 0 if successful + */ +int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out) +{ + int i; + if (md->curlen >= sizeof(md->buf)) { + return -1; + } + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + rmd160_vcompress(md, md->buf); + md->curlen = 0; + } + /* pad upto 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + /* store length */ + STORE64L(md->length, md->buf+56); + rmd160_vcompress(md, md->buf); + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32L(md->state[i], out+(4*i)); + } + return 0; +} + +void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len) +{ + struct rmd160_vstate md; + rmd160_vinit(&md); + rmd160_vprocess(&md,msg,len); + rmd160_vdone(&md, buf); +} +#undef F +#undef G +#undef H +#undef I +#undef J +#undef ROLc +#undef FF +#undef GG +#undef HH +#undef II +#undef JJ +#undef FFF +#undef GGG +#undef HHH +#undef III +#undef JJJ + +static const uint32_t crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size) +{ + const uint8_t *p; + + p = (const uint8_t *)buf; + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} + +void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) +{ + bits256 hash; + vcalc_sha256(0,hash.bytes,data,datalen); + calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); +} + +int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) +{ + bits256 hash; uint8_t *buf,_buf[25]; int32_t len; + memset(rmd160,0,20); + *addrtypep = 0; + buf = _buf; + if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 ) + { + // validate with trailing hash, then remove hash + hash = bits256_doublesha256(0,buf,21); + *addrtypep = *buf; + memcpy(rmd160,buf+1,20); + if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] ) + { + //printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep); + return(20); + } + else + { + int32_t i; + if ( len > 20 ) + { + hash = bits256_doublesha256(0,buf,len); + } + for (i=0; i= 0 ) + return(1); + else return(0); +} + +int32_t bitweight(uint64_t x) +{ + int i,wt = 0; + for (i=0; i<64; i++) + if ( (1LL << i) & x ) + wt++; + return(wt); +} + +char hexbyte(int32_t c) +{ + c &= 0xf; + if ( c < 10 ) + return('0'+c); + else if ( c < 16 ) + return('a'+c-10); + else return(0); +} + +int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len) +{ + int32_t i; + if ( len <= 0 ) + { + hexbytes[0] = 0; + return(1); + } + for (i=0; i>4) & 0xf); + hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); + //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); + } + hexbytes[len*2] = 0; + //printf("len.%ld\n",len*2+1); + return((int32_t)len*2+1); +} + +char *bits256_str(char hexstr[65],bits256 x) +{ + init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); + return(hexstr); +} + +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) +{ + int32_t i; uint64_t x; + if ( rwflag == 0 ) + { + x = 0; + for (i=len-1; i>=0; i--) + { + x <<= 8; + x |= serialized[i]; + } + switch ( len ) + { + case 1: *(uint8_t *)endianedp = (uint8_t)x; break; + case 2: *(uint16_t *)endianedp = (uint16_t)x; break; + case 4: *(uint32_t *)endianedp = (uint32_t)x; break; + case 8: *(uint64_t *)endianedp = (uint64_t)x; break; + } + } + else + { + x = 0; + switch ( len ) + { + case 1: x = *(uint8_t *)endianedp; break; + case 2: x = *(uint16_t *)endianedp; break; + case 4: x = *(uint32_t *)endianedp; break; + case 8: x = *(uint64_t *)endianedp; break; + } + for (i=0; i>= 8) + serialized[i] = (uint8_t)(x & 0xff); + } + return(len); +} + +int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp) +{ + int32_t i; + if ( rwflag == 0 ) + { + for (i=0; i= 0x4c ) + { + if ( opretlen == 0x4c ) + opretlen = script[len++]; + else if ( opretlen == 0x4d ) + { + opretlen = script[len] + (script[len+1] << 8); + len += 2; + //opretlen = script[len++]; + //opretlen = (opretlen << 8) | script[len++]; + } + } + *opretlenp = opretlen; + return(len); +} + +int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen) +{ + int32_t offset = 0; + script[offset++] = 0x6a; + opretlen++; + if ( opretlen >= 0x4c ) + { + if ( opretlen > 0xff ) + { + script[offset++] = 0x4d; + script[offset++] = opretlen & 0xff; + script[offset++] = (opretlen >> 8) & 0xff; + } + else + { + script[offset++] = 0x4c; + script[offset++] = opretlen; + } + } else script[offset++] = opretlen; + script[offset++] = type; // covered by opretlen + memcpy(&script[offset],opret,opretlen-1); + return(offset + opretlen - 1); +} + +// get a pseudo random number that is the same for each block individually at all times and different +// from all other blocks. the sequence is extremely likely, but not guaranteed to be unique for each block chain +uint64_t komodo_block_prg(uint32_t nHeight) +{ + if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) + { + uint64_t i, result = 0, hashSrc64 = ((uint64_t)ASSETCHAINS_MAGIC << 32) | (uint64_t)nHeight; + uint8_t hashSrc[8]; + bits256 hashResult; + + for ( i = 0; i < sizeof(hashSrc); i++ ) + { + uint64_t x = hashSrc64 >> (i * 8); + hashSrc[i] = (uint8_t)(x & 0xff); + } + verus_hash(hashResult.bytes, hashSrc, sizeof(hashSrc)); + for ( i = 0; i < 8; i++ ) + { + result = (result << 8) | hashResult.bytes[i]; + } + return result; + } + else + { + int i; + uint8_t hashSrc[8]; + uint64_t result=0, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight; + bits256 hashResult; + + for ( i = 0; i < sizeof(hashSrc); i++ ) + { + hashSrc[i] = hashSrc64 & 0xff; + hashSrc64 >>= 8; + int8_t b = hashSrc[i]; + } + + vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc)); + for ( i = 0; i < 8; i++ ) + { + result = (result << 8) + hashResult.bytes[i]; + } + return result; + } +} + +// given a block height, this returns the unlock time for that block height, derived from +// the ASSETCHAINS_MAGIC number as well as the block height, providing different random numbers +// for corresponding blocks across chains, but the same sequence in each chain +int64_t komodo_block_unlocktime(uint32_t nHeight) +{ + uint64_t fromTime, toTime, unlocktime; + + if ( ASSETCHAINS_TIMEUNLOCKFROM == ASSETCHAINS_TIMEUNLOCKTO ) + unlocktime = ASSETCHAINS_TIMEUNLOCKTO; + else + { + if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) + { + unlocktime = komodo_block_prg(nHeight) % (ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM); + unlocktime += ASSETCHAINS_TIMEUNLOCKFROM; + } + else + { + unlocktime = komodo_block_prg(nHeight) / (0xffffffffffffffff / ((ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM) + 1)); + // boundary and power of 2 can make it exceed to time by 1 + unlocktime = unlocktime + ASSETCHAINS_TIMEUNLOCKFROM; + if (unlocktime > ASSETCHAINS_TIMEUNLOCKTO) + unlocktime--; + } + } + return ((int64_t)unlocktime); +} + +long _stripwhite(char *buf,int accept) +{ + int32_t i,j,c; + if ( buf == 0 || buf[0] == 0 ) + return(0); + for (i=j=0; buf[i]!=0; i++) + { + buf[j] = c = buf[i]; + if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) + j++; + } + buf[j] = 0; + return(j); +} + +char *clonestr(char *str) +{ + char *clone; + if ( str == 0 || str[0] == 0 ) + { + printf("warning cloning nullstr.%p\n",str); +#ifdef __APPLE__ + while ( 1 ) sleep(1); +#endif + str = (char *)""; + } + clone = (char *)malloc(strlen(str)+16); + strcpy(clone,str); + return(clone); +} + +int32_t safecopy(char *dest,char *src,long len) +{ + int32_t i = -1; + if ( src != 0 && dest != 0 && src != dest ) + { + if ( dest != 0 ) + memset(dest,0,len); + for (i=0; i 0) { + if (xlen < 1048576) i = (int32_t)xlen; else i = 1048576; + i = (int32_t)read(fd,x,i); + if (i < 1) { + sleep(1); + continue; + } + if ( 0 ) + { + int32_t j; + for (j=0; j %p\n",x); + } + x += i; + xlen -= i; + } +} +#endif + +void lock_queue(queue_t *queue) +{ + if ( queue->initflag == 0 ) + { + portable_mutex_init(&queue->mutex); + queue->initflag = 1; + } + portable_mutex_lock(&queue->mutex); +} + +void queue_enqueue(char *name,queue_t *queue,struct queueitem *item) +{ + if ( queue->name[0] == 0 && name != 0 && name[0] != 0 ) + strcpy(queue->name,name); + if ( item == 0 ) + { + printf("FATAL type error: queueing empty value\n"); + return; + } + lock_queue(queue); + DL_APPEND(queue->list,item); + portable_mutex_unlock(&queue->mutex); +} + +struct queueitem *queue_dequeue(queue_t *queue) +{ + struct queueitem *item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + item = queue->list; + DL_DELETE(queue->list,item); + } + portable_mutex_unlock(&queue->mutex); + return(item); +} + +void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize) +{ + struct queueitem *item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + DL_FOREACH(queue->list,item) + { + #ifdef _WIN32 + if ( item == copy || (item->allocsize == copysize && memcmp((void *)((intptr_t)item + sizeof(struct queueitem)),(void *)((intptr_t)copy + sizeof(struct queueitem)),copysize) == 0) ) + #else + if ( item == copy || (item->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)copy + sizeof(struct queueitem)),copysize) == 0) ) + #endif + { + DL_DELETE(queue->list,item); + portable_mutex_unlock(&queue->mutex); + printf("name.(%s) deleted item.%p list.%p\n",queue->name,item,queue->list); + return(item); + } + } + } + portable_mutex_unlock(&queue->mutex); + return(0); +} + +void *queue_free(queue_t *queue) +{ + struct queueitem *item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + DL_FOREACH(queue->list,item) + { + DL_DELETE(queue->list,item); + free(item); + } + //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); + } + portable_mutex_unlock(&queue->mutex); + return(0); +} + +void *queue_clone(queue_t *clone,queue_t *queue,int32_t size) +{ + struct queueitem *ptr,*item = 0; + lock_queue(queue); + if ( queue->list != 0 ) + { + DL_FOREACH(queue->list,item) + { + ptr = (struct queueitem *)calloc(1,sizeof(*ptr)); + memcpy(ptr,item,size); + queue_enqueue(queue->name,clone,ptr); + } + //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); + } + portable_mutex_unlock(&queue->mutex); + return(0); +} + +int32_t queue_size(queue_t *queue) +{ + int32_t count = 0; + struct queueitem *tmp; + lock_queue(queue); + DL_COUNT(queue->list,tmp,count); + portable_mutex_unlock(&queue->mutex); + return count; +} + +void iguana_initQ(queue_t *Q,char *name) +{ + struct queueitem *item,*I; + memset(Q,0,sizeof(*Q)); + I = (struct queueitem *)calloc(1,sizeof(*I)); + strcpy(Q->name,name); + queue_enqueue(name,Q,I); + if ( (item= queue_dequeue(Q)) != 0 ) + free(item); +} + +uint16_t _komodo_userpass(char *username,char *password,FILE *fp) +{ + char *rpcuser,*rpcpassword,*str,line[8192]; uint16_t port = 0; + rpcuser = rpcpassword = 0; + username[0] = password[0] = 0; + while ( fgets(line,sizeof(line),fp) != 0 ) + { + if ( line[0] == '#' ) + continue; + //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); + if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) + rpcuser = parse_conf_line(str,(char *)"rpcuser"); + else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) + rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); + else if ( (str= strstr(line,(char *)"rpcport")) != 0 ) + { + port = atoi(parse_conf_line(str,(char *)"rpcport")); + //fprintf(stderr,"rpcport.%u in file\n",port); + } + } + if ( rpcuser != 0 && rpcpassword != 0 ) + { + strcpy(username,rpcuser); + strcpy(password,rpcpassword); + } + //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); + if ( rpcuser != 0 ) + free(rpcuser); + if ( rpcpassword != 0 ) + free(rpcpassword); + return(port); +} + +void komodo_statefname(char *fname,char *symbol,char *str) +{ + int32_t n,len; + sprintf(fname,"%s",GetDataDir(false).string().c_str()); + if ( (n= (int32_t)strlen(ASSETCHAINS_SYMBOL)) != 0 ) + { + len = (int32_t)strlen(fname); + if ( !mapArgs.count("-datadir") && strcmp(ASSETCHAINS_SYMBOL,&fname[len - n]) == 0 ) + fname[len - n] = 0; + else if(mapArgs.count("-datadir")) printf("DEBUG - komodo_utils:1363: custom datadir\n"); + else + { + if ( strcmp(symbol,"REGTEST") != 0 ) + printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,ASSETCHAINS_SYMBOL,n,len,&fname[len - n]); + return; + } + } + else + { +#ifdef _WIN32 + strcat(fname,"\\"); +#else + strcat(fname,"/"); +#endif + } + if ( symbol != 0 && symbol[0] != 0 && strcmp("KMD",symbol) != 0 ) + { + if(!mapArgs.count("-datadir")) strcat(fname,symbol); + //printf("statefname.(%s) -> (%s)\n",symbol,fname); +#ifdef _WIN32 + strcat(fname,"\\"); +#else + strcat(fname,"/"); +#endif + } + strcat(fname,str); + //printf("test.(%s) -> [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname); +} + +void komodo_configfile(char *symbol,uint16_t rpcport) +{ + static char myusername[512],mypassword[8192]; + FILE *fp; uint16_t kmdport; uint8_t buf2[33]; char fname[512],buf[128],username[512],password[8192]; uint32_t crc,r,r2,i; + if ( symbol != 0 && rpcport != 0 ) + { + r = (uint32_t)time(NULL); + r2 = OS_milliseconds(); + memcpy(buf,&r,sizeof(r)); + memcpy(&buf[sizeof(r)],&r2,sizeof(r2)); + memcpy(&buf[sizeof(r)+sizeof(r2)],symbol,strlen(symbol)); + crc = calc_crc32(0,(uint8_t *)buf,(int32_t)(sizeof(r)+sizeof(r2)+strlen(symbol))); + #ifdef _WIN32 + randombytes_buf(buf2,sizeof(buf2)); + #else + OS_randombytes(buf2,sizeof(buf2)); + #endif + for (i=0; i userpass.(%s)\n",fname,KMDUSERPASS); + } //else printf("couldnt open.(%s)\n",fname); +} + +uint16_t komodo_userpass(char *userpass,char *symbol) +{ + FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN]; + userpass[0] = 0; + if ( strcmp("KMD",symbol) == 0 ) + { +#ifdef __APPLE__ + sprintf(confname,"Komodo.conf"); +#else + sprintf(confname,"komodo.conf"); +#endif + } + else if(!mapArgs.count("-conf")) { + sprintf(confname,"%s.conf",symbol); + komodo_statefname(fname,symbol,confname); + } else sprintf(fname,"%s",GetDataDir().string().c_str()); + + if ( (fp= fopen(fname,"rb")) != 0 ) + { + port = _komodo_userpass(username,password,fp); + sprintf(userpass,"%s:%s",username,password); + if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 ) + strcpy(ASSETCHAINS_USERPASS,userpass); + fclose(fp); + } + return(port); +} + +uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen) +{ + uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; + if ( strcmp(symbol,"KMD") == 0 ) + return(0x8de4eef9); + len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); + strcpy((char *)&buf[len],symbol); + len += strlen(symbol); + if ( extraptr != 0 && extralen != 0 ) + { + vcalc_sha256(0,hash.bytes,extraptr,extralen); + crc0 = hash.uints[0]; + int32_t i; for (i=0; i nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 ) + break; + } + } + if ( curEra <= ASSETCHAINS_LASTERA ) + { + int64_t nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0; + subsidy = (int64_t)ASSETCHAINS_REWARD[curEra]; + if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 0) ) + { + if ( ASSETCHAINS_HALVING[curEra] != 0 ) + { + if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) + { + if ( ASSETCHAINS_DECAY[curEra] == 0 ) + subsidy >>= numhalvings; + else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) + { + if ( curEra == ASSETCHAINS_LASTERA ) + { + subsidyDifference = subsidy; + } + else + { + // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 + subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1]; + if (subsidyDifference < 0) + { + sign = -1; + subsidyDifference *= sign; + } + } + denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart; + numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra])); + subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator); + } + else + { + if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings ) + subsidy = cached_subsidy; + else + { + for (int i=0; i < numhalvings && subsidy != 0; i++) + subsidy = (subsidy * ASSETCHAINS_DECAY[curEra]) / 100000000; + cached_subsidy = subsidy; + cached_numhalvings = numhalvings; + cached_era = curEra; + } + } + } + } + } + } + } + uint32_t magicExtra = ASSETCHAINS_STAKED ? ASSETCHAINS_MAGIC : (ASSETCHAINS_MAGIC & 0xffffff); + if ( ASSETCHAINS_SUPPLY > 10000000000 ) // over 10 billion? + { + if ( nHeight <= ASSETCHAINS_SUPPLY/1000000000 ) + { + subsidy += (uint64_t)1000000000 * COIN; + if ( nHeight == 1 ) + subsidy += (ASSETCHAINS_SUPPLY % 1000000000)*COIN + magicExtra; + } + } + else if ( nHeight == 1 ) + { + if ( ASSETCHAINS_LASTERA == 0 ) + subsidy = ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; + else + subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; + } + else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) + return(0); + // LABS fungible chains, cannot have any block reward! + return(subsidy); +} + +extern int64_t MAX_MONEY; +void komodo_cbopretupdate(int32_t forceflag); +void SplitStr(const std::string& strVal, std::vector &outVals); + +int8_t equihash_params_possible(uint64_t n, uint64_t k) +{ + /* To add more of these you also need to edit: + * equihash.cpp very end of file with the tempate to point to the new param numbers + * equihash.h + * line 210/217 (declaration of equihash class) + * Add this object to the following functions: + * EhInitialiseState + * EhBasicSolve + * EhOptimisedSolve + * EhIsValidSolution + * Alternatively change ASSETCHAINS_N and ASSETCHAINS_K in komodo_nk.h for fast testing. + */ + if ( k == 9 && (n == 200 || n == 210) ) + return(0); + if ( k == 5 && (n == 150 || n == 144 || n == 96 || n == 48) ) + return(0); + if ( k == ASSETCHAINS_K && n == ASSETCHAINS_N) + return(0); + return(-1); +} + +void komodo_args(char *argv0) +{ + std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; + FILE *fp; uint64_t val; uint16_t port, dest_rpc_port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; + + std::string ntz_dest_path; + ntz_dest_path = GetArg("-notary", ""); + IS_KOMODO_NOTARY = ntz_dest_path == "" ? 0 : 1; + + + IS_STAKED_NOTARY = GetArg("-stakednotary", -1); + KOMODO_NSPV = GetArg("-nSPV",0); + memset(ccenables,0,sizeof(ccenables)); + memset(disablebits,0,sizeof(disablebits)); + memset(ccEnablesHeight,0,sizeof(ccEnablesHeight)); + if ( GetBoolArg("-gen", false) != 0 ) + { + KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); + } + if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 ) + fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n"); + DONATION_PUBKEY = GetArg("-donation", ""); + NOTARY_PUBKEY = GetArg("-pubkey", ""); + KOMODO_DEALERNODE = GetArg("-dealer",0); + KOMODO_TESTNODE = GetArg("-testnode",0); + ASSETCHAINS_STAKED_SPLIT_PERCENTAGE = GetArg("-splitperc",0); + if ( strlen(NOTARY_PUBKEY.c_str()) == 66 ) + { + decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + USE_EXTERNAL_PUBKEY = 1; + if ( IS_KOMODO_NOTARY == 0 ) + { + // We dont have any chain data yet, so use system clock to guess. + // I think on season change should reccomend notaries to use -notary to avoid needing this. + int32_t kmd_season = getacseason(time(NULL)); + for (i=0; i<64; i++) + { + if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_elected[kmd_season-1][i][1]) == 0 ) + { + IS_KOMODO_NOTARY = 1; + KOMODO_MININGTHREADS = 1; + mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS); + IS_STAKED_NOTARY = -1; + fprintf(stderr,"running as notary.%d %s\n",i,notaries_elected[kmd_season-1][i][0]); + break; + } + } + } + } + if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) { + fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n"); + StartShutdown(); + } + name = GetArg("-ac_name",""); + if ( argv0 != 0 ) + { + len = (int32_t)strlen(argv0); + for (i=0; i matches suffix (%s) -> ac_name.(%s)\n",argv0,argv0suffix[i],argv0names[i]); + name = argv0names[i]; + break; + } + } + } + KOMODO_STOPAT = GetArg("-stopat",0); + MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); + WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; + ASSETCHAINS_CC = GetArg("-ac_cc",0); + KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0); + ASSETCHAINS_BLOCKTIME = GetArg("-ac_blocktime",60); + ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); + ASSETCHAINS_PRIVATE = GetArg("-ac_private",0); + KOMODO_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0); + Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); + + // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... + Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); + // fill map with all eval codes and activation height of 0. + for ( int i = 0; i < 256; i++ ) + mapHeightEvalActivate[i] = 0; + for ( int i = 0; i < 512; i++ ) + { + int32_t ecode = ccEnablesHeight[i]; + int32_t ht = ccEnablesHeight[i+1]; + if ( i > 1 && ccEnablesHeight[i-2] == ecode ) + break; + if ( ecode > 255 || ecode < 0 ) + fprintf(stderr, "ac_ccactivateht: invalid evalcode.%i must be between 0 and 256.\n", ecode); + else if ( ht > 0 ) + { + // update global map. + mapHeightEvalActivate[ecode] = ht; + fprintf(stderr, "ac_ccactivateht: ecode.%i activates at height.%i\n", ecode, mapHeightEvalActivate[ecode]); + } + i++; + } + + if ( (KOMODO_REWIND= GetArg("-rewind",0)) != 0 ) + { + printf("KOMODO_REWIND %d\n",KOMODO_REWIND); + } + KOMODO_EARLYTXID = Parseuint256(GetArg("-earlytxid","0").c_str()); + ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0); + if ( name.c_str()[0] != 0 ) + { + std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0])); + + for ( int i = 0; i < ASSETCHAINS_NUMALGOS; i++ ) + { + if (std::string(ASSETCHAINS_ALGORITHMS[i]) == selectedAlgo) + { + ASSETCHAINS_ALGO = i; + STAKING_MIN_DIFF = ASSETCHAINS_MINDIFF[i]; + // only worth mentioning if it's not equihash + if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH) + printf("ASSETCHAINS_ALGO, algorithm set to %s\n", selectedAlgo.c_str()); + break; + } + } + if ( ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH && ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0 ) + { + if ( equihash_params_possible(ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]) == -1 ) + { + printf("equihash values N.%li and K.%li are not currently available\n", ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]); + exit(0); + } else printf("ASSETCHAINS_ALGO, algorithm set to equihash with N.%li and K.%li\n", ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]); + } + if (i == ASSETCHAINS_NUMALGOS) + { + printf("ASSETCHAINS_ALGO, %s not supported. using equihash\n", selectedAlgo.c_str()); + } + + ASSETCHAINS_LASTERA = GetArg("-ac_eras", 1); + if ( ASSETCHAINS_LASTERA < 1 || ASSETCHAINS_LASTERA > ASSETCHAINS_MAX_ERAS ) + { + ASSETCHAINS_LASTERA = 1; + printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %lu\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA); + } + ASSETCHAINS_LASTERA -= 1; + + ASSETCHAINS_TIMELOCKGTE = (uint64_t)GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF); + ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0); + ASSETCHAINS_TIMEUNLOCKTO = GetArg("-ac_timeunlockto", 0); + if ( ASSETCHAINS_TIMEUNLOCKFROM > ASSETCHAINS_TIMEUNLOCKTO ) + { + printf("ASSETCHAINS_TIMELOCKGTE - must specify valid ac_timeunlockfrom and ac_timeunlockto\n"); + ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; + ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0; + } + + Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); + Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); + Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); + Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); + Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); + + for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) + { + if ( ASSETCHAINS_DECAY[i] == 100000000 && ASSETCHAINS_ENDSUBSIDY == 0 ) + { + ASSETCHAINS_DECAY[i] = 0; + printf("ERA%u: ASSETCHAINS_DECAY of 100000000 means linear and that needs ASSETCHAINS_ENDSUBSIDY\n", i); + } + else if ( ASSETCHAINS_DECAY[i] > 100000000 ) + { + ASSETCHAINS_DECAY[i] = 0; + printf("ERA%u: ASSETCHAINS_DECAY cant be more than 100000000\n", i); + } + } + + MAX_BLOCK_SIGOPS = 60000; + ASSETCHAINS_TXPOW = GetArg("-ac_txpow",0) & 3; + ASSETCHAINS_FOUNDERS = GetArg("-ac_founders",0);// & 1; + ASSETCHAINS_FOUNDERS_REWARD = GetArg("-ac_founders_reward",0); + ASSETCHAINS_SUPPLY = GetArg("-ac_supply",10); + if ( ASSETCHAINS_SUPPLY > (uint64_t)90*1000*1000000 ) + { + fprintf(stderr,"-ac_supply must be less than 90 billion\n"); + StartShutdown(); + } + fprintf(stderr,"ASSETCHAINS_SUPPLY %llu\n",(long long)ASSETCHAINS_SUPPLY); + + ASSETCHAINS_COMMISSION = GetArg("-ac_perc",0); + ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey",""); + ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); + ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); + ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); + ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0); + ASSETCHAINS_CBOPRET = GetArg("-ac_cbopret",0); + ASSETCHAINS_CBMATURITY = GetArg("-ac_cbmaturity",0); + ASSETCHAINS_ADAPTIVEPOW = GetArg("-ac_adaptivepow",0); + //fprintf(stderr,"ASSETCHAINS_CBOPRET.%llx\n",(long long)ASSETCHAINS_CBOPRET); + if ( ASSETCHAINS_CBOPRET != 0 ) + { + SplitStr(GetArg("-ac_prices",""), ASSETCHAINS_PRICES); + if ( ASSETCHAINS_PRICES.size() > 0 ) + ASSETCHAINS_CBOPRET |= 4; + SplitStr(GetArg("-ac_stocks",""), ASSETCHAINS_STOCKS); + if ( ASSETCHAINS_STOCKS.size() > 0 ) + ASSETCHAINS_CBOPRET |= 8; + for (i=0; i 0 ) + { + for (i=0; i<256; i++) + { + ASSETCHAINS_CCDISABLES[i] = 1; + SETBIT(disablebits,i); + } + for (i=0; i 0 ) + { + for (i=first; i<=last; i++) + { + CLEARBIT(disablebits,i); + ASSETCHAINS_CCDISABLES[i] = 0; + } + }*/ + } + if ( ASSETCHAINS_BEAMPORT != 0 ) + { + fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n"); + StartShutdown(); + } + ASSETCHAINS_SELFIMPORT = GetArg("-ac_import",""); // BEAM, CODA, PUBKEY, GATEWAY + if ( ASSETCHAINS_SELFIMPORT == "PUBKEY" ) + { + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) != 66 ) + { + fprintf(stderr,"invalid -ac_pubkey for -ac_import=PUBKEY\n"); + StartShutdown(); + } + } + else if ( ASSETCHAINS_SELFIMPORT == "BEAM" ) + { + if (ASSETCHAINS_BEAMPORT == 0) + { + fprintf(stderr,"missing -ac_beam for BEAM rpcport\n"); + StartShutdown(); + } + } + else if ( ASSETCHAINS_SELFIMPORT == "CODA" ) + { + if (ASSETCHAINS_CODAPORT == 0) + { + fprintf(stderr,"missing -ac_coda for CODA rpcport\n"); + StartShutdown(); + } + } + else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") + { + Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); + if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) + { + fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); + StartShutdown(); + } + } + // else it can be gateway coin + else if (!ASSETCHAINS_SELFIMPORT.empty() && (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_SUPPLY>0 || ASSETCHAINS_COMMISSION!=0)) + { + fprintf(stderr,"when using gateway import these must be set: -ac_end=1 -ac_supply=0 -ac_perc=0\n"); + StartShutdown(); + } + + + if ( (ASSETCHAINS_STAKED= GetArg("-ac_staked",0)) > 100 ) + ASSETCHAINS_STAKED = 100; + + // for now, we only support 50% PoS due to other parts of the algorithm needing adjustment for + // other values + if ( (ASSETCHAINS_LWMAPOS = GetArg("-ac_veruspos",0)) != 0 ) + { + ASSETCHAINS_LWMAPOS = 50; + } + ASSETCHAINS_SAPLING = GetArg("-ac_sapling", -1); + if (ASSETCHAINS_SAPLING == -1) + { + ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", -1); + } + else + { + ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", ASSETCHAINS_SAPLING); + } + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 || ASSETCHAINS_SCRIPTPUB.size() > 1 ) + { + if ( ASSETCHAINS_SUPPLY > 10000000000 ) + { + printf("ac_pubkey or ac_script wont work with ac_supply over 10 billion\n"); + StartShutdown(); + } + if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) + { + printf("Assetchains NOTARY PAY cannot be used with ac_pubkey or ac_script.\n"); + StartShutdown(); + } + if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 ) + { + decode_hex(ASSETCHAINS_OVERRIDE_PUBKEY33,33,(char *)ASSETCHAINS_OVERRIDE_PUBKEY.c_str()); + calc_rmd160_sha256(ASSETCHAINS_OVERRIDE_PUBKEYHASH,ASSETCHAINS_OVERRIDE_PUBKEY33,33); + } + if ( ASSETCHAINS_COMMISSION == 0 && ASSETCHAINS_FOUNDERS != 0 ) + { + if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) + { + ASSETCHAINS_COMMISSION = 53846154; // maps to 35% + printf("ASSETCHAINS_COMMISSION defaulted to 35%% when founders reward active\n"); + } + else + { + printf("ASSETCHAINS_FOUNDERS_REWARD set to %ld\n", ASSETCHAINS_FOUNDERS_REWARD); + } + /*else if ( ASSETCHAINS_SELFIMPORT.size() == 0 ) + { + //ASSETCHAINS_OVERRIDE_PUBKEY.clear(); + printf("-ac_perc must be set with -ac_pubkey\n"); + }*/ + } + } + else + { + if ( ASSETCHAINS_COMMISSION != 0 ) + { + ASSETCHAINS_COMMISSION = 0; + printf("ASSETCHAINS_COMMISSION needs an ASSETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n"); + } + if ( ASSETCHAINS_FOUNDERS != 0 ) + { + ASSETCHAINS_FOUNDERS = 0; + printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n"); + } + } + if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_MARMARA != 0 ) + { + fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n"); + StartShutdown(); + } + if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 ) + { + fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); + extraptr = extrabuf; + memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; + + // if we have one era, this should create the same data structure as it used to, same if we increase _MAX_ERAS + for ( int i = 0; i <= ASSETCHAINS_LASTERA; i++ ) + { + printf("ERA%u: end.%llu reward.%llu halving.%llu decay.%llu notarypay.%llu\n", i, + (long long)ASSETCHAINS_ENDSUBSIDY[i], + (long long)ASSETCHAINS_REWARD[i], + (long long)ASSETCHAINS_HALVING[i], + (long long)ASSETCHAINS_DECAY[i], + (long long)ASSETCHAINS_NOTARY_PAY[i]); + + // TODO: Verify that we don't overrun extrabuf here, which is a 256 byte buffer + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ENDSUBSIDY[i]),(void *)&ASSETCHAINS_ENDSUBSIDY[i]); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD[i]),(void *)&ASSETCHAINS_REWARD[i]); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING[i]),(void *)&ASSETCHAINS_HALVING[i]); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY[i]),(void *)&ASSETCHAINS_DECAY[i]); + if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NOTARY_PAY[i]),(void *)&ASSETCHAINS_NOTARY_PAY[i]); + } + + if (ASSETCHAINS_LASTERA > 0) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LASTERA),(void *)&ASSETCHAINS_LASTERA); + } + + // hash in lock above for time locked coinbase transactions above a certain reward value only if the lock above + // param was specified, otherwise, for compatibility, do nothing + if ( ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF ) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMELOCKGTE),(void *)&ASSETCHAINS_TIMELOCKGTE); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKFROM),(void *)&ASSETCHAINS_TIMEUNLOCKFROM); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKTO),(void *)&ASSETCHAINS_TIMEUNLOCKTO); + } + + if ( ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH ) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); + } + + if ( ASSETCHAINS_LWMAPOS != 0 ) + { + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS); + } + + val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); + + if ( ASSETCHAINS_FOUNDERS != 0 ) + { + uint8_t tmp = 1; + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(tmp),(void *)&tmp); + if ( ASSETCHAINS_FOUNDERS > 1 ) + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS); + if ( ASSETCHAINS_FOUNDERS_REWARD != 0 ) + { + fprintf(stderr, "set founders reward.%lld\n",(long long)ASSETCHAINS_FOUNDERS_REWARD); + extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD); + } + } + if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) + { + decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + extralen += ASSETCHAINS_SCRIPTPUB.size()/2; + //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); + fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); + } + if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) + { + memcpy(&extraptr[extralen],(char *)ASSETCHAINS_SELFIMPORT.c_str(),ASSETCHAINS_SELFIMPORT.size()); + for (i=0; i 0 ) + { + memcpy(&extraptr[extralen],disablebits,sizeof(disablebits)); + extralen += sizeof(disablebits); + } + if ( ASSETCHAINS_CCLIB.size() > 1 ) + { + for (i=0; i 0 ) + ASSETCHAINS_SEED = 1; + + strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); + + MAX_MONEY = komodo_max_money(); + + if ( (baseid = komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) + { + //komodo_maxallowed(baseid); + printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); + } + + if ( ASSETCHAINS_CC >= KOMODO_FIRSTFUNGIBLEID && MAX_MONEY < 1000000LL*SATOSHIDEN ) + MAX_MONEY = 1000000LL*SATOSHIDEN; + if ( KOMODO_BIT63SET(MAX_MONEY) != 0 ) + MAX_MONEY = KOMODO_MAXNVALUE; + fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); + //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); + uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); + if ( GetArg("-port",0) != 0 ) + { + ASSETCHAINS_P2PPORT = GetArg("-port",0); + fprintf(stderr,"set p2pport.%u\n",ASSETCHAINS_P2PPORT); + } else ASSETCHAINS_P2PPORT = tmpport; + + while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) + { + fprintf(stderr,"waiting for datadir (%s)\n",dirname); +#ifndef _WIN32 + sleep(3); +#else + boost::this_thread::sleep(boost::posix_time::milliseconds(3000)); +#endif + } + //fprintf(stderr,"Got datadir.(%s)\n",dirname); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + int32_t komodo_baseid(char *origbase); + extern int COINBASE_MATURITY; + if ( strcmp(ASSETCHAINS_SYMBOL,"KMD") == 0 ) + { + fprintf(stderr,"cant have assetchain named KMD\n"); + StartShutdown(); + } + if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) + ASSETCHAINS_RPCPORT = port; + else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); + + if (ASSETCHAINS_CBMATURITY != 0) + COINBASE_MATURITY = ASSETCHAINS_CBMATURITY; + else if (ASSETCHAINS_LASTERA == 0 || is_STAKED(ASSETCHAINS_SYMBOL) != 0) + COINBASE_MATURITY = 1; + if (COINBASE_MATURITY < 1) + { + fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); + StartShutdown(); + } + //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); + } + if ( ASSETCHAINS_RPCPORT == 0 ) + ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; + //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); + //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); + iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); + for (i=0; i<4; i++) + sprintf(&magicstr[i<<1],"%02x",magic[i]); + magicstr[8] = 0; +#ifndef FROM_CLI + sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); + if ( (fp= fopen(fname,"wb")) != 0 ) + { + int8_t notarypay = 0; + if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) + notarypay = 1; + fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146",notarypay); + fclose(fp); + //printf("created (%s)\n",fname); + } else printf("error creating (%s)\n",fname); +#endif + if ( ASSETCHAINS_CC < 2 ) + { + if ( KOMODO_CCACTIVATE != 0 ) + { + ASSETCHAINS_CC = 2; + fprintf(stderr,"smart utxo CC contracts will activate at height.%d\n",KOMODO_CCACTIVATE); + } + else if ( ccEnablesHeight[0] != 0 ) + { + ASSETCHAINS_CC = 2; + fprintf(stderr,"smart utxo CC contract %d will activate at height.%d\n",(int32_t)ccEnablesHeight[0],(int32_t)ccEnablesHeight[1]); + } + } + } + else + { + char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; + ASSETCHAINS_P2PPORT = 7770; + ASSETCHAINS_RPCPORT = 7771; + for (iter=0; iter<2; iter++) + { + strcpy(fname,GetDataDir().string().c_str()); +#ifdef _WIN32 + while ( fname[strlen(fname)-1] != '\\' ) + fname[strlen(fname)-1] = 0; + if ( iter == 0 ) + strcat(fname,"Komodo\\komodo.conf"); + else strcat(fname,ntz_dest_path.c_str()); +#else + while ( fname[strlen(fname)-1] != '/' ) + fname[strlen(fname)-1] = 0; +#ifdef __APPLE__ + if ( iter == 0 ) + strcat(fname,"Komodo/Komodo.conf"); + else strcat(fname,ntz_dest_path.c_str()); +#else + if ( iter == 0 ) + strcat(fname,".komodo/komodo.conf"); + else strcat(fname,ntz_dest_path.c_str()); +#endif +#endif + if ( (fp= fopen(fname,"rb")) != 0 ) + { + dest_rpc_port = _komodo_userpass(username,password,fp); + DEST_PORT = iter == 1 ? dest_rpc_port : 0; + sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); + fclose(fp); + } else printf("couldnt open.(%s) will not validate dest notarizations\n",fname); + if ( IS_KOMODO_NOTARY == 0 ) + break; + } + } + int32_t dpowconfs = KOMODO_DPOWCONFS; + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); + //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); + if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) + { + ASSETCHAINS_HALVING[0] *= 5; + fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%llu\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,(long long)ASSETCHAINS_LASTERA); + } + else if ( strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 ) + dpowconfs = 0; + else if ( ASSETCHAINS_PRIVATE != 0 ) + { + fprintf(stderr,"-ac_private for a non-PIRATE chain is not supported. The only reason to have an -ac_private chain is for total privacy and that is best achieved with the largest anon set. PIRATE has that and it is recommended to just use PIRATE\n"); + StartShutdown(); + } + // Set cc enables for all existing ac_cc chains here. + if ( strcmp("AXO",ASSETCHAINS_SYMBOL) == 0 ) + { + // No CCs used on this chain yet. + CCDISABLEALL; + } + if ( strcmp("CCL",ASSETCHAINS_SYMBOL) == 0 ) + { + // No CCs used on this chain yet. + CCDISABLEALL; + CCENABLE(EVAL_TOKENS); + CCENABLE(EVAL_HEIR); + } + if ( strcmp("COQUI",ASSETCHAINS_SYMBOL) == 0 ) + { + CCDISABLEALL; + CCENABLE(EVAL_DICE); + CCENABLE(EVAL_CHANNELS); + CCENABLE(EVAL_ORACLES); + CCENABLE(EVAL_ASSETS); + CCENABLE(EVAL_TOKENS); + } + if ( strcmp("DION",ASSETCHAINS_SYMBOL) == 0 ) + { + // No CCs used on this chain yet. + CCDISABLEALL; + } + + if ( strcmp("EQL",ASSETCHAINS_SYMBOL) == 0 ) + { + // No CCs used on this chain yet. + CCDISABLEALL; + } + if ( strcmp("ILN",ASSETCHAINS_SYMBOL) == 0 ) + { + // No CCs used on this chain yet. + CCDISABLEALL; + } + if ( strcmp("OUR",ASSETCHAINS_SYMBOL) == 0 ) + { + // No CCs used on this chain yet. + CCDISABLEALL; + } + if ( strcmp("ZEXO",ASSETCHAINS_SYMBOL) == 0 ) + { + // No CCs used on this chain yet. + CCDISABLEALL; + } + if ( strcmp("SEC",ASSETCHAINS_SYMBOL) == 0 ) + { + CCDISABLEALL; + CCENABLE(EVAL_ASSETS); + CCENABLE(EVAL_TOKENS); + CCENABLE(EVAL_ORACLES); + } + if ( strcmp("KMDICE",ASSETCHAINS_SYMBOL) == 0 ) + { + CCDISABLEALL; + CCENABLE(EVAL_FAUCET); + CCENABLE(EVAL_DICE); + CCENABLE(EVAL_ORACLES); + } + } else BITCOIND_RPCPORT = GetArg("-rpcport", BaseParams().RPCPort()); + KOMODO_DPOWCONFS = GetArg("-dpowconfs",dpowconfs); + if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"SUPERNET") == 0 || strcmp(ASSETCHAINS_SYMBOL,"DEX") == 0 || strcmp(ASSETCHAINS_SYMBOL,"COQUI") == 0 || strcmp(ASSETCHAINS_SYMBOL,"PIRATE") == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDICE") == 0 ) + KOMODO_EXTRASATOSHI = 1; +} + +void komodo_nameset(char *symbol,char *dest,char *source) +{ + if ( source[0] == 0 ) + { + strcpy(symbol,(char *)"KMD"); + strcpy(dest,(char *)"BTC"); + } + else + { + strcpy(symbol,source); + strcpy(dest,(char *)"KMD"); + } +} + +struct komodo_state *komodo_stateptrget(char *base) +{ + int32_t baseid; + if ( base == 0 || base[0] == 0 || strcmp(base,(char *)"KMD") == 0 ) + return(&KOMODO_STATES[33]); + else if ( (baseid= komodo_baseid(base)) >= 0 ) + return(&KOMODO_STATES[baseid+1]); + else return(&KOMODO_STATES[0]); +} + +struct komodo_state *komodo_stateptr(char *symbol,char *dest) +{ + int32_t baseid; + komodo_nameset(symbol,dest,ASSETCHAINS_SYMBOL); + return(komodo_stateptrget(symbol)); +} + +void komodo_prefetch(FILE *fp) +{ + long fsize,fpos; int32_t incr = 16*1024*1024; + fpos = ftell(fp); + fseek(fp,0,SEEK_END); + fsize = ftell(fp); + if ( fsize > incr ) + { + char *ignore = (char *)malloc(incr); + if ( ignore != 0 ) + { + rewind(fp); + while ( fread(ignore,1,incr,fp) == incr ) // prefetch + fprintf(stderr,"."); + free(ignore); + } + } + fseek(fp,fpos,SEEK_SET); +} + +// check if block timestamp is more than S5 activation time +// this function is to activate the ExtractDestination fix +bool komodo_is_vSolutionsFixActive() +{ + return GetLatestTimestamp(komodo_currentheight()) > nS5Timestamp; +} diff --git a/src/komodo_utils.h b/src/komodo_utils.h index f21241cccc2..861fc8486a3 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -42,7 +42,7 @@ typedef struct queue char name[64],initflag; } queue_t; -#include "mini-gmp.c" +#include "mini-gmp.h" #define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" #define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" @@ -822,77 +822,6 @@ int32_t bitweight(uint64_t x) return(wt); } -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i Date: Tue, 1 Jun 2021 06:35:55 -0500 Subject: [PATCH 10/58] More moving of implementation to .cpp files --- src/cc/dapps/dappstd.c | 4 +- src/cc/rogue/main.c | 4 +- src/komodo.h | 2 +- src/komodo_bitcoind.cpp | 32 +- src/komodo_bitcoind.h | 2 +- src/komodo_cutils.cpp | 72 ++ src/komodo_cutils.h | 71 +- src/komodo_gateway.cpp | 4 +- src/komodo_gateway.h | 2 - src/komodo_jumblr.cpp | 4 + src/komodo_kv.cpp | 1 + src/komodo_notary.cpp | 798 +------------- src/komodo_pax.cpp | 3 + src/komodo_utils.cpp | 308 ++++++ src/komodo_utils.h | 2135 +------------------------------------- src/main.cpp | 1 - src/primitives/nonce.h | 2 +- src/rpc/server.cpp | 11 - src/rpc/server.h | 10 - src/wallet/rpcwallet.cpp | 186 ---- 20 files changed, 463 insertions(+), 3189 deletions(-) create mode 100644 src/komodo_cutils.cpp diff --git a/src/cc/dapps/dappstd.c b/src/cc/dapps/dappstd.c index 82366315c95..e949ea18135 100644 --- a/src/cc/dapps/dappstd.c +++ b/src/cc/dapps/dappstd.c @@ -243,9 +243,9 @@ int32_t safecopy(char *dest,char *src,long len) #define true 1 #define false 0 //#ifdef STANDALONE -//#include "../komodo/src/komodo_cJSON.c" +//#include "../komodo/src/komodo_cJSON.h" //#else -#include "../komodo_cJSON.c" +#include "../komodo_cJSON.h" //#endif int32_t games_replay(uint64_t seed,int32_t sleeptime); diff --git a/src/cc/rogue/main.c b/src/cc/rogue/main.c index 093b73d703d..c2bb82487c6 100644 --- a/src/cc/rogue/main.c +++ b/src/cc/rogue/main.c @@ -254,9 +254,9 @@ int32_t safecopy(char *dest,char *src,long len) #define true 1 #define false 0 #ifdef STANDALONE -#include "../komodo/src/komodo_cJSON.c" +#include "../komodo/src/komodo_cJSON.h" #else -#include "../../komodo_cJSON.c" +#include "../../komodo_cJSON.h" #endif int32_t rogue_replay(uint64_t seed,int32_t sleeptime); diff --git a/src/komodo.h b/src/komodo.h index 5094b16e48b..0c107d4347d 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -42,7 +42,7 @@ bool check_pprevnotarizedht(); #include "komodo_utils.h" #include "komodo_curve25519.h" -#include "komodo_cJSON.c" +#include "komodo_cJSON.h" #include "komodo_bitcoind.h" #include "komodo_interest.h" #include "komodo_pax.h" diff --git a/src/komodo_bitcoind.cpp b/src/komodo_bitcoind.cpp index 1baa1f7b50c..1e59fc74122 100644 --- a/src/komodo_bitcoind.cpp +++ b/src/komodo_bitcoind.cpp @@ -13,6 +13,8 @@ * * ******************************************************************************/ #include "komodo_bitcoind.h" +#include "komodo_utils.h" // OS_milliseconds +#include "komodo_globals.h" /************************************************************************ * @@ -604,11 +606,7 @@ uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, { CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts; *valuep = 0; - if (!GetTransaction(hash, tx, -#ifndef KOMODO_ZCASH - Params().GetConsensus(), -#endif - hashBlock, true)) + if (!GetTransaction(hash, tx, hashBlock, true)) { //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); return(0); @@ -635,11 +633,7 @@ uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr) { CTxDestination address; CBlockIndex *pindex; CTransaction tx; uint256 hashBlock; uint32_t txtime = 0; *valuep = 0; - if (!GetTransaction(hash, tx, -#ifndef KOMODO_ZCASH - Params().GetConsensus(), -#endif - hashBlock, true)) + if (!GetTransaction(hash, tx, hashBlock, true)) { //fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime); return(0); @@ -854,7 +848,7 @@ int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block) if ( block->vtx[0].vout.size() > 0 ) { txnouttype whichType; - vector> vch = vector>(); + std::vector> vch; if (Solver(block->vtx[0].vout[0].scriptPubKey, whichType, vch) && whichType == TX_PUBKEY) { CPubKey pubKey(vch[0]); @@ -1836,11 +1830,7 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) fprintf(stderr,"ERROR: chain not fully loaded or invalid PoS block %s - no past block found\n",blkHash.ToString().c_str()); } else -#ifndef KOMODO_ZCASH - if (!GetTransaction(txid, tx, Params().GetConsensus(), blkHash, true)) -#else if (!GetTransaction(txid, tx, blkHash, true)) -#endif { fprintf(stderr,"ERROR: invalid PoS block %s - no source transaction\n",blkHash.ToString().c_str()); } @@ -2592,16 +2582,6 @@ int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height) *sproutfundsp = sproutfunds; 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) { @@ -2631,7 +2611,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt { static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime; int32_t PoSperc = 0, newStakerActive; - set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; + std::set setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; std::vector vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock; uint64_t cbPerc = *utxovaluep, tocoinbase = 0; if (!EnsureWalletIsAvailable(0)) return 0; diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index cb170b921ec..735b8f0986b 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#pragma once // komodo functions that interact with bitcoind C++ #include diff --git a/src/komodo_cutils.cpp b/src/komodo_cutils.cpp new file mode 100644 index 00000000000..f0ca6887f96 --- /dev/null +++ b/src/komodo_cutils.cpp @@ -0,0 +1,72 @@ +#include "komodo_cutils.h" + +int32_t _unhex(char c) +{ + if ( c >= '0' && c <= '9' ) + return(c - '0'); + else if ( c >= 'a' && c <= 'f' ) + return(c - 'a' + 10); + else if ( c >= 'A' && c <= 'F' ) + return(c - 'A' + 10); + return(-1); +} + +int32_t unhex(char c) +{ + int32_t hex; + if ( (hex= _unhex(c)) < 0 ) + { + //printf("unhex: illegal hexchar.(%c)\n",c); + } + return(hex); +} + +int32_t is_hexstr(char *str,int32_t n) +{ + int32_t i; + if ( str == 0 || str[0] == 0 ) + return(0); + for (i=0; str[i]!=0; i++) + { + if ( n > 0 && i >= n ) + break; + if ( _unhex(str[i]) < 0 ) + break; + } + if ( n == 0 ) + return(i); + return(i == n); +} + +unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } + +int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) +{ + int32_t adjust,i = 0; + //printf("decode.(%s)\n",hex); + if ( is_hexstr(hex,n) <= 0 ) + { + memset(bytes,0,n); + return(n); + } + if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) + hex[--n] = 0; + if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) + { + if ( n > 0 ) + { + bytes[0] = unhex(hex[0]); + printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); + } + bytes++; + hex++; + adjust = 1; + } else adjust = 0; + if ( n > 0 ) + { + for (i=0; i= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} +unsigned char _decode_hex(char *hex); -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} +int32_t unhex(char c); -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} +int32_t is_hexstr(char *str,int32_t n); -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i"},...] ( minconf ) ( fee ) - */ - -#ifdef _WIN32 -#include -#endif -#include "komodo_defs.h" - -#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" -#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" -#define JUMBLR_MAXSECRETADDRS 777 -#define JUMBLR_SYNCHRONIZED_BLOCKS 10 -#define JUMBLR_INCR 9.965 -#define JUMBLR_FEE 0.001 -#define JUMBLR_TXFEE 0.01 -#define SMALLVAL 0.000000000000001 - -#define JUMBLR_ERROR_DUPLICATEDEPOSIT -1 -#define JUMBLR_ERROR_SECRETCANTBEDEPOSIT -2 -#define JUMBLR_ERROR_TOOMANYSECRETS -3 -#define JUMBLR_ERROR_NOTINWALLET -4 - -struct jumblr_item -{ - UT_hash_handle hh; - int64_t amount,fee,txfee; // fee and txfee not really used (yet) - uint32_t spent,pad; - char opid[66],src[128],dest[128],status; -} *Jumblrs; - -char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64]; -int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode - -char *jumblr_issuemethod(char *userpass,char *method,char *params,uint16_t port) -{ - cJSON *retjson,*resjson = 0; char *retstr; - if ( (retstr= komodo_issuemethod(userpass,method,params,port)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"result") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"result")); - else if ( jobj(retjson,(char *)"error") != 0 ) - resjson = jduplicate(jobj(retjson,(char *)"error")); - else - { - resjson = cJSON_CreateObject(); - jaddstr(resjson,(char *)"error",(char *)"cant parse return"); - } - free_json(retjson); - } - free(retstr); - } - if ( resjson != 0 ) - return(jprint(resjson,1)); - else return(clonestr((char *)"{\"error\":\"unknown error\"}")); -} - -char *jumblr_importaddress(char *address) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"%s\", false]",address,address); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_validateaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\"]",addr); - printf("validateaddress.%s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,BITCOIND_RPCPORT)); -} - -int32_t Jumblr_secretaddrfind(char *searchaddr) -{ - int32_t i; - for (i=0; i 0 ) - { - OS_randombytes((uint8_t *)&r,sizeof(r)); - r %= Jumblr_numsecretaddrs; - safecopy(secretaddr,Jumblr_secretaddrs[r],64); - } - return(r); -} - -int32_t jumblr_addresstype(char *addr) -{ - if ( addr[0] == '"' && addr[strlen(addr)-1] == '"' ) - { - addr[strlen(addr)-1] = 0; - addr++; - } - if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) - return('z'); - else if ( strlen(addr) < 40 ) - return('t'); - printf("strange.(%s)\n",addr); - return(-1); -} - -struct jumblr_item *jumblr_opidfind(char *opid) -{ - struct jumblr_item *ptr; - HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr); - return(ptr); -} - -struct jumblr_item *jumblr_opidadd(char *opid) -{ - struct jumblr_item *ptr = 0; - if ( opid != 0 && (ptr= jumblr_opidfind(opid)) == 0 ) - { - ptr = (struct jumblr_item *)calloc(1,sizeof(*ptr)); - safecopy(ptr->opid,opid,sizeof(ptr->opid)); - HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); - if ( ptr != jumblr_opidfind(opid) ) - printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); - } - return(ptr); -} - -char *jumblr_zgetnewaddress() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistoperationids() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetoperationresult(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetoperationstatus(char *opid) -{ - char params[1024]; - sprintf(params,"[[\"%s\"]]",opid); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount) -{ - char params[1024]; double fee = ((amount-3*JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in t to z\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("t -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount) -{ - char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; - if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to z\"}")); - //sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_TXFEE); - printf("z -> z: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount) -{ - char params[1024]; double fee = ((amount-JUMBLR_TXFEE) * JUMBLR_FEE) * 1.5; - if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' ) - return(clonestr((char *)"{\"error\":\"illegal address in z to t\"}")); - sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); - printf("z -> t: %s\n",params); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistaddresses() -{ - char params[1024]; - sprintf(params,"[]"); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listaddresses",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zlistreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_getreceivedbyaddress(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,BITCOIND_RPCPORT)); -} - -char *jumblr_importprivkey(char *wifstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", \"\", false]",wifstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,BITCOIND_RPCPORT)); -} - -char *jumblr_zgetbalance(char *addr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",addr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,BITCOIND_RPCPORT)); -} - -char *jumblr_listunspent(char *coinaddr) -{ - char params[1024]; - sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"listunspent",params,BITCOIND_RPCPORT)); -} - -char *jumblr_gettransaction(char *txidstr) -{ - char params[1024]; - sprintf(params,"[\"%s\", 1]",txidstr); - return(jumblr_issuemethod(KMDUSERPASS,(char *)"getrawtransaction",params,BITCOIND_RPCPORT)); -} - -int32_t jumblr_numvins(bits256 txid) -{ - char txidstr[65],params[1024],*retstr; cJSON *retjson,*vins; int32_t n,numvins = -1; - bits256_str(txidstr,txid); - if ( (retstr= jumblr_gettransaction(txidstr)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,(char *)"vin") != 0 && ((vins= jarray(&n,retjson,(char *)"vin")) == 0 || n == 0) ) - { - numvins = n; - //printf("numvins.%d\n",n); - } //else printf("no vin.(%s)\n",retstr); - free_json(retjson); - } - free(retstr); - } - return(numvins); -} - -int64_t jumblr_receivedby(char *addr) -{ - char *retstr; int64_t total = 0; - if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 ) - { - total = atof(retstr) * SATOSHIDEN; - free(retstr); - } - return(total); -} - -int64_t jumblr_balance(char *addr) -{ - char *retstr; double val; int64_t balance = 0; //cJSON *retjson; int32_t i,n; - /*if ( jumblr_addresstype(addr) == 't' ) - { - if ( (retstr= jumblr_listunspent(addr)) != 0 ) - { - //printf("jumblr.[%s].(%s)\n","KMD",retstr); - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(retjson)) > 0 && cJSON_IsArray(retjson) != 0 ) - for (i=0; i SMALLVAL ) - balance = val * SATOSHIDEN; - free(retstr); - } - return(balance); -} - -int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) -{ - cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; - /*"params" : { - "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", - "amounts" : [ - { - "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", - "amount" : 3.00000000 - } - ], - "minconf" : 1, - "fee" : 0.00010000 - }*/ - if ( (params= jobj(item,(char *)"params")) != 0 ) - { - //printf("params.(%s)\n",jprint(params,0)); - if ( (from= jstr(params,(char *)"fromaddress")) != 0 ) - { - safecopy(ptr->src,from,sizeof(ptr->src)); - } - if ( (amounts= jarray(&n,params,(char *)"amounts")) != 0 ) - { - for (i=0; i 0 ) - { - if ( strcmp(addr,JUMBLR_ADDR) == 0 ) - ptr->fee = amount; - else - { - ptr->amount = amount; - safecopy(ptr->dest,addr,sizeof(ptr->dest)); - } - } - } - } - ptr->txfee = jdouble(params,(char *)"fee") * SATOSHIDEN; - } - return(1); -} - -void jumblr_opidupdate(struct jumblr_item *ptr) -{ - char *retstr,*status; cJSON *retjson,*item; - if ( ptr->status == 0 ) - { - if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 ) - { - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( cJSON_GetArraySize(retjson) == 1 && cJSON_IsArray(retjson) != 0 ) - { - item = jitem(retjson,0); - //printf("%s\n",jprint(item,0)); - if ( (status= jstr(item,(char *)"status")) != 0 ) - { - if ( strcmp(status,(char *)"success") == 0 ) - { - ptr->status = jumblr_itemset(ptr,item,status); - if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) ) - { - printf("a non-jumblr t->z pruned\n"); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - - } - else if ( strcmp(status,(char *)"failed") == 0 ) - { - printf("jumblr_opidupdate %s failed\n",ptr->opid); - free(jumblr_zgetoperationresult(ptr->opid)); - ptr->status = -1; - } - } - } - free_json(retjson); - } - free(retstr); - } - } -} - -void jumblr_prune(struct jumblr_item *ptr) -{ - struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; - if ( is_hexstr(ptr->opid,0) == 64 ) - return; - printf("jumblr_prune %s\n",ptr->opid); - strcpy(oldsrc,ptr->src); - free(jumblr_zgetoperationresult(ptr->opid)); - while ( flag != 0 ) - { - flag = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( strcmp(oldsrc,ptr->dest) == 0 ) - { - if ( is_hexstr(ptr->opid,0) != 64 ) - { - printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); - free(jumblr_zgetoperationresult(ptr->opid)); - strcpy(oldsrc,ptr->src); - flag = 1; - break; - } - } - } - } -} - - -bits256 jbits256(cJSON *json,char *field); - - -void jumblr_zaddrinit(char *zaddr) -{ - struct jumblr_item *ptr; char *retstr,*totalstr; cJSON *item,*array; double total; bits256 txid; char txidstr[65],t_z,z_z; - if ( (totalstr= jumblr_zgetbalance(zaddr)) != 0 ) - { - if ( (total= atof(totalstr)) > SMALLVAL ) - { - if ( (retstr= jumblr_zlistreceivedbyaddress(zaddr)) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - t_z = z_z = 0; - if ( cJSON_GetArraySize(array) == 1 && cJSON_IsArray(array) != 0 ) - { - item = jitem(array,0); - if ( (uint64_t)((total+0.0000000049) * SATOSHIDEN) == (uint64_t)((jdouble(item,(char *)"amount")+0.0000000049) * SATOSHIDEN) ) - { - txid = jbits256(item,(char *)"txid"); - bits256_str(txidstr,txid); - if ( (ptr= jumblr_opidadd(txidstr)) != 0 ) - { - ptr->amount = (total * SATOSHIDEN); - ptr->status = 1; - strcpy(ptr->dest,zaddr); - if ( jumblr_addresstype(ptr->dest) != 'z' ) - printf("error setting dest type to Z: %s\n",jprint(item,0)); - if ( jumblr_numvins(txid) == 0 ) - { - z_z = 1; - strcpy(ptr->src,zaddr); - ptr->src[3] = '0'; - ptr->src[4] = '0'; - ptr->src[5] = '0'; - if ( jumblr_addresstype(ptr->src) != 'z' ) - printf("error setting address type to Z: %s\n",jprint(item,0)); - } - else - { - t_z = 1; - strcpy(ptr->src,"taddr"); - if ( jumblr_addresstype(ptr->src) != 't' ) - printf("error setting address type to T: %s\n",jprint(item,0)); - } - printf("%s %s %.8f t_z.%d z_z.%d\n",zaddr,txidstr,total,t_z,z_z); // cant be z->t from spend - } - } else printf("mismatched %s %s total %.8f vs %.8f -> %lld\n",zaddr,totalstr,dstr(SATOSHIDEN * total),dstr(SATOSHIDEN * jdouble(item,(char *)"amount")),(long long)((uint64_t)(total * SATOSHIDEN) - (uint64_t)(jdouble(item,(char *)"amount") * SATOSHIDEN))); - } - free_json(array); - } - free(retstr); - } - } - free(totalstr); - } -} - -void jumblr_opidsupdate() -{ - char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; - if ( (retstr= jumblr_zlistoperationids()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - //printf("%s -> n%d\n",retstr,n); - for (i=0; istatus == 0 ) - jumblr_opidupdate(ptr); - //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); - if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' ) - jumblr_prune(ptr); - } - } - } - free_json(array); - } - free(retstr); - } -} - -uint64_t jumblr_increment(uint8_t r,int32_t height,uint64_t total,uint64_t biggest,uint64_t medium, uint64_t smallest) -{ - int32_t i,n; uint64_t incrs[1000],remains = total; - height /= JUMBLR_SYNCHRONIZED_BLOCKS; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) == 0 || total >= 100*biggest ) - { - if ( total >= biggest ) - return(biggest); - else if ( total >= medium ) - return(medium); - else if ( total >= smallest ) - return(smallest); - else return(0); - } - else - { - n = 0; - while ( remains > smallest && n < sizeof(incrs)/sizeof(*incrs) ) - { - if ( remains >= biggest ) - incrs[n] = biggest; - else if ( remains >= medium ) - incrs[n] = medium; - else if ( remains >= smallest ) - incrs[n] = smallest; - else break; - remains -= incrs[n]; - n++; - } - if ( n > 0 ) - { - r %= n; - for (i=0; i %.8f\n",n,r,dstr(incrs[r])); - return(incrs[r]); - } - } - return(0); -} - -void jumblr_iteration() -{ - static int32_t lastheight; static uint32_t lasttime; - char *zaddr,*addr,*retstr=0,secretaddr[64]; cJSON *array; int32_t i,iter,height,acpublic,counter,chosen_one,n; uint64_t smallest,medium,biggest,amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint16_t r,s; - acpublic = ASSETCHAINS_PUBLIC; - if ( ASSETCHAINS_SYMBOL[0] == 0 && GetTime() >= KOMODO_SAPLING_DEADLINE ) - acpublic = 1; - if ( JUMBLR_PAUSE != 0 || acpublic != 0 ) - return; - if ( lasttime == 0 ) - { - if ( (retstr= jumblr_zlistaddresses()) != 0 ) - { - if ( (array= cJSON_Parse(retstr)) != 0 ) - { - if ( (n= cJSON_GetArraySize(array)) > 0 && cJSON_IsArray(array) != 0 ) - { - for (i=0; iGetHeight(); - if ( time(NULL) < lasttime+40 ) - return; - lasttime = (uint32_t)time(NULL); - if ( lastheight == height ) - return; - lastheight = height; - if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != JUMBLR_SYNCHRONIZED_BLOCKS-3 ) - return; - fee = JUMBLR_INCR * JUMBLR_FEE; - smallest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); - medium = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - biggest = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*777 + 3*JUMBLR_TXFEE); - OS_randombytes((uint8_t *)&r,sizeof(r)); - s = (r % 3); - //printf("jumblr_iteration r.%u s.%u\n",r,s); - switch ( s ) - { - case 0: // t -> z - default: - if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= smallest ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - amount = jumblr_increment(r/3,height,total,biggest,medium,smallest); - /* - amount = 0; - if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); - else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) - amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); - else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);*/ - if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,addr,dstr(amount))) != 0 ) - { - printf("sendt_to_z.(%s)\n",retstr); - free(retstr), retstr = 0; - } - free(zaddr); - } else printf("no zaddr from jumblr_zgetnewaddress\n"); - } - else if ( Jumblr_deposit[0] != 0 ) - printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); - break; - case 1: // z -> z - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=counter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - if ( (zaddr= jumblr_zgetnewaddress()) != 0 ) - { - if ( zaddr[0] == '"' && zaddr[strlen(zaddr)-1] == '"' ) - { - zaddr[strlen(zaddr)-1] = 0; - addr = zaddr+1; - } else addr = zaddr; - if ( (retstr= jumblr_sendz_to_z(ptr->dest,addr,dstr(total))) != 0 ) - { - printf("n.%d counter.%d chosen_one.%d send z_to_z.(%s)\n",n,counter,chosen_one,retstr); - free(retstr), retstr = 0; - } - ptr->spent = (uint32_t)time(NULL); - free(zaddr); - break; - } - } - counter++; - } - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } - } - break; - case 2: // z -> t - if ( Jumblr_numsecretaddrs > 0 ) - { - jumblr_opidsupdate(); - chosen_one = -1; - for (iter=0; iter<2; iter++) - { - counter = n = 0; - HASH_ITER(hh,Jumblrs,ptr,tmp) - { - //printf("status.%d %c %c %.8f\n",ptr->status,jumblr_addresstype(ptr->src),jumblr_addresstype(ptr->dest),dstr(ptr->amount)); - if ( ptr->spent == 0 && ptr->status > 0 && jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' ) - { - if ( (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) - { - if ( iter == 1 && counter == chosen_one ) - { - Jumblr_secretaddr(secretaddr); - if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 ) - { - printf("%s send z_to_t.(%s)\n",secretaddr,retstr); - free(retstr), retstr = 0; - } else printf("null return from jumblr_sendz_to_t\n"); - ptr->spent = (uint32_t)time(NULL); - break; - } - counter++; - } //else printf("z->t spent.%u total %.8f error\n",ptr->spent,dstr(total)); - } - n++; - } - if ( counter == 0 ) - break; - if ( iter == 0 ) - { - OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); - if ( chosen_one < 0 ) - chosen_one = -chosen_one; - chosen_one %= counter; - printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); - } //else printf("n.%d counter.%d chosen.%d\n",n,counter,chosen_one); - } - } - break; - } -} std::lock_guard lock(komodo_mutex); sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); np = &sp->NPOINTS[sp->NUM_NPOINTS++]; diff --git a/src/komodo_pax.cpp b/src/komodo_pax.cpp index ecbd584ce86..5d913d1bbf0 100644 --- a/src/komodo_pax.cpp +++ b/src/komodo_pax.cpp @@ -13,6 +13,9 @@ * * ******************************************************************************/ #include "komodo_pax.h" +#include "komodo_utils.h" // iguana_rwnum +#include "komodo_globals.h" // komodo_mutex +#include "komodo.h" // KOMODO_PAXMAX uint64_t komodo_maxallowed(int32_t baseid) { diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index 33243aa2689..d270b39f6ae 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -13,6 +13,7 @@ * * ******************************************************************************/ #include "komodo_utils.h" +#include "komodo_globals.h" void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) { @@ -32,6 +33,273 @@ bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) return(hash); } +// rmd160: the five basic functions F(), G() and H() +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) +#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) \ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define GG(a, b, c, d, e, x, s) \ +(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define HH(a, b, c, d, e, x, s) \ +(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define II(a, b, c, d, e, x, s) \ +(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define JJ(a, b, c, d, e, x, s) \ +(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define FFF(a, b, c, d, e, x, s) \ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define GGG(a, b, c, d, e, x, s) \ +(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define HHH(a, b, c, d, e, x, s) \ +(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define III(a, b, c, d, e, x, s) \ +(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +#define JJJ(a, b, c, d, e, x, s) \ +(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ +(a) = ROLc((a), (s)) + (e);\ +(c) = ROLc((c), 10); + +static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf) +{ + uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = aaa = md->state[0]; + bb = bbb = md->state[1]; + cc = ccc = md->state[2]; + dd = ddd = md->state[3]; + ee = eee = md->state[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + md->state[1]; /* final result for md->state[0] */ + md->state[1] = md->state[2] + dd + eee; + md->state[2] = md->state[3] + ee + aaa; + md->state[3] = md->state[4] + aa + bbb; + md->state[4] = md->state[0] + bb + ccc; + md->state[0] = ddd; + + return 0; +} + /** Initialize the hash state @param md The hash state you wish to initialize @@ -49,6 +317,46 @@ int rmd160_vinit(struct rmd160_vstate * md) return 0; } +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return 0 if successful + */ +int rmd160_vprocess (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + int err; + if (md->curlen > sizeof(md->buf)) { + return -1; + } + while (inlen > 0) { + if (md->curlen == 0 && inlen >= 64) { + if ((err = rmd160_vcompress (md, (unsigned char *)in)) != 0) { + return err; + } + md->length += 64 * 8; + in += 64; + inlen -= 64; + } else { + n = MIN(inlen, (64 - md->curlen)); + memcpy(md->buf + md->curlen, in, (size_t)n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == 64) { + if ((err = rmd160_vcompress (md, md->buf)) != 0) { + return err; + } + md->length += 8*64; + md->curlen = 0; + } + } + } + return 0; +} + /** Terminate the hash to get the digest @param md The hash state diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 861fc8486a3..4301cfd93c6 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -12,6 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#pragma once #include "komodo_defs.h" #include "key_io.h" #include "cc/CCinclude.h" @@ -275,341 +276,16 @@ static inline int32_t sha256_vdone(struct sha256_vstate *md,uint8_t *out) return(0); } -void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) -{ - struct sha256_vstate md; - sha256_vinit(&md); - sha256_vprocess(&md,src,len); - sha256_vdone(&md,hash); -} - -bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) -{ - bits256 hash,hash2; int32_t i; - vcalc_sha256(0,hash.bytes,data,datalen); - vcalc_sha256(0,hash2.bytes,hash.bytes,sizeof(hash)); - for (i=0; i>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -/* the ten basic operations FF() through III() */ -#define FF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define II(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define FFF(a, b, c, d, e, x, s) \ -(a) += F((b), (c), (d)) + (x);\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define GGG(a, b, c, d, e, x, s) \ -(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define HHH(a, b, c, d, e, x, s) \ -(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define III(a, b, c, d, e, x, s) \ -(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -#define JJJ(a, b, c, d, e, x, s) \ -(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ -(a) = ROLc((a), (s)) + (e);\ -(c) = ROLc((c), 10); - -static int32_t rmd160_vcompress(struct rmd160_vstate *md,uint8_t *buf) -{ - uint32_t aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; - int i; +void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); - /* load words X */ - for (i = 0; i < 16; i++){ - LOAD32L(X[i], buf + (4 * i)); - } - - /* load state */ - aa = aaa = md->state[0]; - bb = bbb = md->state[1]; - cc = ccc = md->state[2]; - dd = ddd = md->state[3]; - ee = eee = md->state[4]; - - /* round 1 */ - FF(aa, bb, cc, dd, ee, X[ 0], 11); - FF(ee, aa, bb, cc, dd, X[ 1], 14); - FF(dd, ee, aa, bb, cc, X[ 2], 15); - FF(cc, dd, ee, aa, bb, X[ 3], 12); - FF(bb, cc, dd, ee, aa, X[ 4], 5); - FF(aa, bb, cc, dd, ee, X[ 5], 8); - FF(ee, aa, bb, cc, dd, X[ 6], 7); - FF(dd, ee, aa, bb, cc, X[ 7], 9); - FF(cc, dd, ee, aa, bb, X[ 8], 11); - FF(bb, cc, dd, ee, aa, X[ 9], 13); - FF(aa, bb, cc, dd, ee, X[10], 14); - FF(ee, aa, bb, cc, dd, X[11], 15); - FF(dd, ee, aa, bb, cc, X[12], 6); - FF(cc, dd, ee, aa, bb, X[13], 7); - FF(bb, cc, dd, ee, aa, X[14], 9); - FF(aa, bb, cc, dd, ee, X[15], 8); - - /* round 2 */ - GG(ee, aa, bb, cc, dd, X[ 7], 7); - GG(dd, ee, aa, bb, cc, X[ 4], 6); - GG(cc, dd, ee, aa, bb, X[13], 8); - GG(bb, cc, dd, ee, aa, X[ 1], 13); - GG(aa, bb, cc, dd, ee, X[10], 11); - GG(ee, aa, bb, cc, dd, X[ 6], 9); - GG(dd, ee, aa, bb, cc, X[15], 7); - GG(cc, dd, ee, aa, bb, X[ 3], 15); - GG(bb, cc, dd, ee, aa, X[12], 7); - GG(aa, bb, cc, dd, ee, X[ 0], 12); - GG(ee, aa, bb, cc, dd, X[ 9], 15); - GG(dd, ee, aa, bb, cc, X[ 5], 9); - GG(cc, dd, ee, aa, bb, X[ 2], 11); - GG(bb, cc, dd, ee, aa, X[14], 7); - GG(aa, bb, cc, dd, ee, X[11], 13); - GG(ee, aa, bb, cc, dd, X[ 8], 12); - - /* round 3 */ - HH(dd, ee, aa, bb, cc, X[ 3], 11); - HH(cc, dd, ee, aa, bb, X[10], 13); - HH(bb, cc, dd, ee, aa, X[14], 6); - HH(aa, bb, cc, dd, ee, X[ 4], 7); - HH(ee, aa, bb, cc, dd, X[ 9], 14); - HH(dd, ee, aa, bb, cc, X[15], 9); - HH(cc, dd, ee, aa, bb, X[ 8], 13); - HH(bb, cc, dd, ee, aa, X[ 1], 15); - HH(aa, bb, cc, dd, ee, X[ 2], 14); - HH(ee, aa, bb, cc, dd, X[ 7], 8); - HH(dd, ee, aa, bb, cc, X[ 0], 13); - HH(cc, dd, ee, aa, bb, X[ 6], 6); - HH(bb, cc, dd, ee, aa, X[13], 5); - HH(aa, bb, cc, dd, ee, X[11], 12); - HH(ee, aa, bb, cc, dd, X[ 5], 7); - HH(dd, ee, aa, bb, cc, X[12], 5); - - /* round 4 */ - II(cc, dd, ee, aa, bb, X[ 1], 11); - II(bb, cc, dd, ee, aa, X[ 9], 12); - II(aa, bb, cc, dd, ee, X[11], 14); - II(ee, aa, bb, cc, dd, X[10], 15); - II(dd, ee, aa, bb, cc, X[ 0], 14); - II(cc, dd, ee, aa, bb, X[ 8], 15); - II(bb, cc, dd, ee, aa, X[12], 9); - II(aa, bb, cc, dd, ee, X[ 4], 8); - II(ee, aa, bb, cc, dd, X[13], 9); - II(dd, ee, aa, bb, cc, X[ 3], 14); - II(cc, dd, ee, aa, bb, X[ 7], 5); - II(bb, cc, dd, ee, aa, X[15], 6); - II(aa, bb, cc, dd, ee, X[14], 8); - II(ee, aa, bb, cc, dd, X[ 5], 6); - II(dd, ee, aa, bb, cc, X[ 6], 5); - II(cc, dd, ee, aa, bb, X[ 2], 12); - - /* round 5 */ - JJ(bb, cc, dd, ee, aa, X[ 4], 9); - JJ(aa, bb, cc, dd, ee, X[ 0], 15); - JJ(ee, aa, bb, cc, dd, X[ 5], 5); - JJ(dd, ee, aa, bb, cc, X[ 9], 11); - JJ(cc, dd, ee, aa, bb, X[ 7], 6); - JJ(bb, cc, dd, ee, aa, X[12], 8); - JJ(aa, bb, cc, dd, ee, X[ 2], 13); - JJ(ee, aa, bb, cc, dd, X[10], 12); - JJ(dd, ee, aa, bb, cc, X[14], 5); - JJ(cc, dd, ee, aa, bb, X[ 1], 12); - JJ(bb, cc, dd, ee, aa, X[ 3], 13); - JJ(aa, bb, cc, dd, ee, X[ 8], 14); - JJ(ee, aa, bb, cc, dd, X[11], 11); - JJ(dd, ee, aa, bb, cc, X[ 6], 8); - JJ(cc, dd, ee, aa, bb, X[15], 5); - JJ(bb, cc, dd, ee, aa, X[13], 6); - - /* parallel round 1 */ - JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); - JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); - JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); - JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); - JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); - JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); - JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); - JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); - JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); - JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); - JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); - - /* parallel round 2 */ - III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); - III(ddd, eee, aaa, bbb, ccc, X[11], 13); - III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); - III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); - III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); - III(eee, aaa, bbb, ccc, ddd, X[13], 8); - III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); - III(ccc, ddd, eee, aaa, bbb, X[10], 11); - III(bbb, ccc, ddd, eee, aaa, X[14], 7); - III(aaa, bbb, ccc, ddd, eee, X[15], 7); - III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); - III(ddd, eee, aaa, bbb, ccc, X[12], 7); - III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); - III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); - III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); - III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); - - /* parallel round 3 */ - HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); - HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); - HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); - HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); - HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); - HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); - HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); - HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); - HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); - HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); - HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); - HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); - HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); - HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); - HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); - HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); - - /* parallel round 4 */ - GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); - GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); - GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); - GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); - GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); - GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); - GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); - GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); - GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); - GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); - GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); - GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); - GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); - GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); - GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); - GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); - - /* parallel round 5 */ - FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); - FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); - FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); - FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); - FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); - FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); - FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); - FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); - FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); - FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); - FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); - FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); - FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); - FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); - FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); - - /* combine results */ - ddd += cc + md->state[1]; /* final result for md->state[0] */ - md->state[1] = md->state[2] + dd + eee; - md->state[2] = md->state[3] + ee + aaa; - md->state[3] = md->state[4] + aa + bbb; - md->state[4] = md->state[0] + bb + ccc; - md->state[0] = ddd; - - return 0; -} +bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); /** Initialize the hash state @param md The hash state you wish to initialize @return 0 if successful */ -int rmd160_vinit(struct rmd160_vstate * md) -{ - md->state[0] = 0x67452301UL; - md->state[1] = 0xefcdab89UL; - md->state[2] = 0x98badcfeUL; - md->state[3] = 0x10325476UL; - md->state[4] = 0xc3d2e1f0UL; - md->curlen = 0; - md->length = 0; - return 0; -} -#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ -int func_name (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen) \ -{ \ -unsigned long n; \ -int err; \ -if (md->curlen > sizeof(md->buf)) { \ -return -1; \ -} \ -while (inlen > 0) { \ -if (md->curlen == 0 && inlen >= block_size) { \ -if ((err = compress_name (md, (unsigned char *)in)) != 0) { \ -return err; \ -} \ -md->length += block_size * 8; \ -in += block_size; \ -inlen -= block_size; \ -} else { \ -n = MIN(inlen, (block_size - md->curlen)); \ -memcpy(md->buf + md->curlen, in, (size_t)n); \ -md->curlen += n; \ -in += n; \ -inlen -= n; \ -if (md->curlen == block_size) { \ -if ((err = compress_name (md, md->buf)) != 0) { \ -return err; \ -} \ -md->length += 8*block_size; \ -md->curlen = 0; \ -} \ -} \ -} \ -return 0; \ -} +int rmd160_vinit(struct rmd160_vstate * md); /** Process a block of memory though the hash @@ -618,7 +294,7 @@ return 0; @param inlen The length of the data (octets) @return 0 if successful */ -HASH_PROCESS(rmd160_vprocess, rmd160_vcompress, rmd160, 64) +int rmd160_vprocess (struct rmd160_vstate * md, const unsigned char *in, unsigned long inlen); /** Terminate the hash to get the digest @@ -626,1810 +302,103 @@ HASH_PROCESS(rmd160_vprocess, rmd160_vcompress, rmd160, 64) @param out [out] The destination of the hash (20 bytes) @return 0 if successful */ -int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out) -{ - int i; - if (md->curlen >= sizeof(md->buf)) { - return -1; - } - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char)0; - } - rmd160_vcompress(md, md->buf); - md->curlen = 0; - } - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char)0; - } - /* store length */ - STORE64L(md->length, md->buf+56); - rmd160_vcompress(md, md->buf); - /* copy output */ - for (i = 0; i < 5; i++) { - STORE32L(md->state[i], out+(4*i)); - } - return 0; -} - -void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len) -{ - struct rmd160_vstate md; - rmd160_vinit(&md); - rmd160_vprocess(&md,msg,len); - rmd160_vdone(&md, buf); -} -#undef F -#undef G -#undef H -#undef I -#undef J -#undef ROLc -#undef FF -#undef GG -#undef HH -#undef II -#undef JJ -#undef FFF -#undef GGG -#undef HHH -#undef III -#undef JJJ - -static const uint32_t crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size) -{ - const uint8_t *p; +int rmd160_vdone(struct rmd160_vstate * md, unsigned char *out); - p = (const uint8_t *)buf; - crc = crc ^ ~0U; +void calc_rmd160(char deprecated[41],uint8_t buf[20],uint8_t *msg,int32_t len); - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - - return crc ^ ~0U; -} +uint32_t calc_crc32(uint32_t crc,const void *buf,size_t size); -void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) -{ - bits256 hash; - vcalc_sha256(0,hash.bytes,data,datalen); - calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); -} +void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen); -int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr) -{ - bits256 hash; uint8_t *buf,_buf[25]; int32_t len; - memset(rmd160,0,20); - *addrtypep = 0; - buf = _buf; - if ( (len= bitcoin_base58decode(buf,coinaddr)) >= 4 ) - { - // validate with trailing hash, then remove hash - hash = bits256_doublesha256(0,buf,21); - *addrtypep = *buf; - memcpy(rmd160,buf+1,20); - if ( (buf[21]&0xff) == hash.bytes[31] && (buf[22]&0xff) == hash.bytes[30] &&(buf[23]&0xff) == hash.bytes[29] && (buf[24]&0xff) == hash.bytes[28] ) - { - //printf("coinaddr.(%s) valid checksum addrtype.%02x\n",coinaddr,*addrtypep); - return(20); - } - else - { - int32_t i; - if ( len > 20 ) - { - hash = bits256_doublesha256(0,buf,len); - } - for (i=0; i= 0 ) - return(1); - else return(0); -} +int32_t komodo_is_issuer(); -int32_t bitweight(uint64_t x) -{ - int i,wt = 0; - for (i=0; i<64; i++) - if ( (1LL << i) & x ) - wt++; - return(wt); -} +int32_t bitweight(uint64_t x); -char hexbyte(int32_t c) -{ - c &= 0xf; - if ( c < 10 ) - return('0'+c); - else if ( c < 16 ) - return('a'+c-10); - else return(0); -} +char hexbyte(int32_t c); -int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len) -{ - int32_t i; - if ( len <= 0 ) - { - hexbytes[0] = 0; - return(1); - } - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} +int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len); -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} +char *bits256_str(char hexstr[65],bits256 x); -int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) -{ - int32_t i; uint64_t x; - if ( rwflag == 0 ) - { - x = 0; - for (i=len-1; i>=0; i--) - { - x <<= 8; - x |= serialized[i]; - } - switch ( len ) - { - case 1: *(uint8_t *)endianedp = (uint8_t)x; break; - case 2: *(uint16_t *)endianedp = (uint16_t)x; break; - case 4: *(uint32_t *)endianedp = (uint32_t)x; break; - case 8: *(uint64_t *)endianedp = (uint64_t)x; break; - } - } - else - { - x = 0; - switch ( len ) - { - case 1: x = *(uint8_t *)endianedp; break; - case 2: x = *(uint16_t *)endianedp; break; - case 4: x = *(uint32_t *)endianedp; break; - case 8: x = *(uint64_t *)endianedp; break; - } - for (i=0; i>= 8) - serialized[i] = (uint8_t)(x & 0xff); - } - return(len); -} +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); -int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *endianedp) -{ - int32_t i; - if ( rwflag == 0 ) - { - for (i=0; i= 0x4c ) - { - if ( opretlen == 0x4c ) - opretlen = script[len++]; - else if ( opretlen == 0x4d ) - { - opretlen = script[len] + (script[len+1] << 8); - len += 2; - //opretlen = script[len++]; - //opretlen = (opretlen << 8) | script[len++]; - } - } - *opretlenp = opretlen; - return(len); -} +int32_t komodo_scriptitemlen(int32_t *opretlenp,uint8_t *script); -int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen) -{ - int32_t offset = 0; - script[offset++] = 0x6a; - opretlen++; - if ( opretlen >= 0x4c ) - { - if ( opretlen > 0xff ) - { - script[offset++] = 0x4d; - script[offset++] = opretlen & 0xff; - script[offset++] = (opretlen >> 8) & 0xff; - } - else - { - script[offset++] = 0x4c; - script[offset++] = opretlen; - } - } else script[offset++] = opretlen; - script[offset++] = type; // covered by opretlen - memcpy(&script[offset],opret,opretlen-1); - return(offset + opretlen - 1); -} +int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); // get a pseudo random number that is the same for each block individually at all times and different // from all other blocks. the sequence is extremely likely, but not guaranteed to be unique for each block chain -uint64_t komodo_block_prg(uint32_t nHeight) -{ - if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) - { - uint64_t i, result = 0, hashSrc64 = ((uint64_t)ASSETCHAINS_MAGIC << 32) | (uint64_t)nHeight; - uint8_t hashSrc[8]; - bits256 hashResult; - - for ( i = 0; i < sizeof(hashSrc); i++ ) - { - uint64_t x = hashSrc64 >> (i * 8); - hashSrc[i] = (uint8_t)(x & 0xff); - } - verus_hash(hashResult.bytes, hashSrc, sizeof(hashSrc)); - for ( i = 0; i < 8; i++ ) - { - result = (result << 8) | hashResult.bytes[i]; - } - return result; - } - else - { - int i; - uint8_t hashSrc[8]; - uint64_t result=0, hashSrc64 = (uint64_t)ASSETCHAINS_MAGIC << 32 + nHeight; - bits256 hashResult; - - for ( i = 0; i < sizeof(hashSrc); i++ ) - { - hashSrc[i] = hashSrc64 & 0xff; - hashSrc64 >>= 8; - int8_t b = hashSrc[i]; - } - - vcalc_sha256(0, hashResult.bytes, hashSrc, sizeof(hashSrc)); - for ( i = 0; i < 8; i++ ) - { - result = (result << 8) + hashResult.bytes[i]; - } - return result; - } -} +uint64_t komodo_block_prg(uint32_t nHeight); // given a block height, this returns the unlock time for that block height, derived from // the ASSETCHAINS_MAGIC number as well as the block height, providing different random numbers // for corresponding blocks across chains, but the same sequence in each chain -int64_t komodo_block_unlocktime(uint32_t nHeight) -{ - uint64_t fromTime, toTime, unlocktime; - - if ( ASSETCHAINS_TIMEUNLOCKFROM == ASSETCHAINS_TIMEUNLOCKTO ) - unlocktime = ASSETCHAINS_TIMEUNLOCKTO; - else - { - if (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || nHeight >= 12800) - { - unlocktime = komodo_block_prg(nHeight) % (ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM); - unlocktime += ASSETCHAINS_TIMEUNLOCKFROM; - } - else - { - unlocktime = komodo_block_prg(nHeight) / (0xffffffffffffffff / ((ASSETCHAINS_TIMEUNLOCKTO - ASSETCHAINS_TIMEUNLOCKFROM) + 1)); - // boundary and power of 2 can make it exceed to time by 1 - unlocktime = unlocktime + ASSETCHAINS_TIMEUNLOCKFROM; - if (unlocktime > ASSETCHAINS_TIMEUNLOCKTO) - unlocktime--; - } - } - return ((int64_t)unlocktime); -} +int64_t komodo_block_unlocktime(uint32_t nHeight); -long _stripwhite(char *buf,int accept) -{ - int32_t i,j,c; - if ( buf == 0 || buf[0] == 0 ) - return(0); - for (i=j=0; buf[i]!=0; i++) - { - buf[j] = c = buf[i]; - if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) - j++; - } - buf[j] = 0; - return(j); -} +long _stripwhite(char *buf,int accept); -char *clonestr(char *str) -{ - char *clone; - if ( str == 0 || str[0] == 0 ) - { - printf("warning cloning nullstr.%p\n",str); -#ifdef __APPLE__ - while ( 1 ) sleep(1); -#endif - str = (char *)""; - } - clone = (char *)malloc(strlen(str)+16); - strcpy(clone,str); - return(clone); -} +char *clonestr(char *str); -int32_t safecopy(char *dest,char *src,long len) -{ - int32_t i = -1; - if ( src != 0 && dest != 0 && src != dest ) - { - if ( dest != 0 ) - memset(dest,0,len); - for (i=0; i 0) { - if (xlen < 1048576) i = (int32_t)xlen; else i = 1048576; - i = (int32_t)read(fd,x,i); - if (i < 1) { - sleep(1); - continue; - } - if ( 0 ) - { - int32_t j; - for (j=0; j %p\n",x); - } - x += i; - xlen -= i; - } -} -#endif +void lock_queue(queue_t *queue); -void lock_queue(queue_t *queue) -{ - if ( queue->initflag == 0 ) - { - portable_mutex_init(&queue->mutex); - queue->initflag = 1; - } - portable_mutex_lock(&queue->mutex); -} +void queue_enqueue(char *name,queue_t *queue,struct queueitem *item); -void queue_enqueue(char *name,queue_t *queue,struct queueitem *item) -{ - if ( queue->name[0] == 0 && name != 0 && name[0] != 0 ) - strcpy(queue->name,name); - if ( item == 0 ) - { - printf("FATAL type error: queueing empty value\n"); - return; - } - lock_queue(queue); - DL_APPEND(queue->list,item); - portable_mutex_unlock(&queue->mutex); -} +struct queueitem *queue_dequeue(queue_t *queue); -struct queueitem *queue_dequeue(queue_t *queue) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - item = queue->list; - DL_DELETE(queue->list,item); - } - portable_mutex_unlock(&queue->mutex); - return(item); -} +void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize); -void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - #ifdef _WIN32 - if ( item == copy || (item->allocsize == copysize && memcmp((void *)((intptr_t)item + sizeof(struct queueitem)),(void *)((intptr_t)copy + sizeof(struct queueitem)),copysize) == 0) ) - #else - if ( item == copy || (item->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)copy + sizeof(struct queueitem)),copysize) == 0) ) - #endif - { - DL_DELETE(queue->list,item); - portable_mutex_unlock(&queue->mutex); - printf("name.(%s) deleted item.%p list.%p\n",queue->name,item,queue->list); - return(item); - } - } - } - portable_mutex_unlock(&queue->mutex); - return(0); -} +void *queue_free(queue_t *queue); -void *queue_free(queue_t *queue) -{ - struct queueitem *item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - DL_DELETE(queue->list,item); - free(item); - } - //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); - } - portable_mutex_unlock(&queue->mutex); - return(0); -} +void *queue_clone(queue_t *clone,queue_t *queue,int32_t size); -void *queue_clone(queue_t *clone,queue_t *queue,int32_t size) -{ - struct queueitem *ptr,*item = 0; - lock_queue(queue); - if ( queue->list != 0 ) - { - DL_FOREACH(queue->list,item) - { - ptr = (struct queueitem *)calloc(1,sizeof(*ptr)); - memcpy(ptr,item,size); - queue_enqueue(queue->name,clone,ptr); - } - //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); - } - portable_mutex_unlock(&queue->mutex); - return(0); -} +int32_t queue_size(queue_t *queue); -int32_t queue_size(queue_t *queue) -{ - int32_t count = 0; - struct queueitem *tmp; - lock_queue(queue); - DL_COUNT(queue->list,tmp,count); - portable_mutex_unlock(&queue->mutex); - return count; -} +void iguana_initQ(queue_t *Q,char *name); -void iguana_initQ(queue_t *Q,char *name) -{ - struct queueitem *item,*I; - memset(Q,0,sizeof(*Q)); - I = (struct queueitem *)calloc(1,sizeof(*I)); - strcpy(Q->name,name); - queue_enqueue(name,Q,I); - if ( (item= queue_dequeue(Q)) != 0 ) - free(item); -} +uint16_t _komodo_userpass(char *username,char *password,FILE *fp); -uint16_t _komodo_userpass(char *username,char *password,FILE *fp) -{ - char *rpcuser,*rpcpassword,*str,line[8192]; uint16_t port = 0; - rpcuser = rpcpassword = 0; - username[0] = password[0] = 0; - while ( fgets(line,sizeof(line),fp) != 0 ) - { - if ( line[0] == '#' ) - continue; - //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); - if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) - rpcuser = parse_conf_line(str,(char *)"rpcuser"); - else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) - rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); - else if ( (str= strstr(line,(char *)"rpcport")) != 0 ) - { - port = atoi(parse_conf_line(str,(char *)"rpcport")); - //fprintf(stderr,"rpcport.%u in file\n",port); - } - } - if ( rpcuser != 0 && rpcpassword != 0 ) - { - strcpy(username,rpcuser); - strcpy(password,rpcpassword); - } - //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); - if ( rpcuser != 0 ) - free(rpcuser); - if ( rpcpassword != 0 ) - free(rpcpassword); - return(port); -} +void komodo_statefname(char *fname,char *symbol,char *str); -void komodo_statefname(char *fname,char *symbol,char *str) -{ - int32_t n,len; - sprintf(fname,"%s",GetDataDir(false).string().c_str()); - if ( (n= (int32_t)strlen(ASSETCHAINS_SYMBOL)) != 0 ) - { - len = (int32_t)strlen(fname); - if ( !mapArgs.count("-datadir") && strcmp(ASSETCHAINS_SYMBOL,&fname[len - n]) == 0 ) - fname[len - n] = 0; - else if(mapArgs.count("-datadir")) printf("DEBUG - komodo_utils:1363: custom datadir\n"); - else - { - if ( strcmp(symbol,"REGTEST") != 0 ) - printf("unexpected fname.(%s) vs %s [%s] n.%d len.%d (%s)\n",fname,symbol,ASSETCHAINS_SYMBOL,n,len,&fname[len - n]); - return; - } - } - else - { -#ifdef _WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - } - if ( symbol != 0 && symbol[0] != 0 && strcmp("KMD",symbol) != 0 ) - { - if(!mapArgs.count("-datadir")) strcat(fname,symbol); - //printf("statefname.(%s) -> (%s)\n",symbol,fname); -#ifdef _WIN32 - strcat(fname,"\\"); -#else - strcat(fname,"/"); -#endif - } - strcat(fname,str); - //printf("test.(%s) -> [%s] statename.(%s) %s\n",test,ASSETCHAINS_SYMBOL,symbol,fname); -} +void komodo_configfile(char *symbol,uint16_t rpcport); -void komodo_configfile(char *symbol,uint16_t rpcport) -{ - static char myusername[512],mypassword[8192]; - FILE *fp; uint16_t kmdport; uint8_t buf2[33]; char fname[512],buf[128],username[512],password[8192]; uint32_t crc,r,r2,i; - if ( symbol != 0 && rpcport != 0 ) - { - r = (uint32_t)time(NULL); - r2 = OS_milliseconds(); - memcpy(buf,&r,sizeof(r)); - memcpy(&buf[sizeof(r)],&r2,sizeof(r2)); - memcpy(&buf[sizeof(r)+sizeof(r2)],symbol,strlen(symbol)); - crc = calc_crc32(0,(uint8_t *)buf,(int32_t)(sizeof(r)+sizeof(r2)+strlen(symbol))); - #ifdef _WIN32 - randombytes_buf(buf2,sizeof(buf2)); - #else - OS_randombytes(buf2,sizeof(buf2)); - #endif - for (i=0; i userpass.(%s)\n",fname,KMDUSERPASS); - } //else printf("couldnt open.(%s)\n",fname); -} +uint16_t komodo_userpass(char *userpass,char *symbol); -uint16_t komodo_userpass(char *userpass,char *symbol) -{ - FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[KOMODO_ASSETCHAIN_MAXLEN]; - userpass[0] = 0; - if ( strcmp("KMD",symbol) == 0 ) - { -#ifdef __APPLE__ - sprintf(confname,"Komodo.conf"); -#else - sprintf(confname,"komodo.conf"); -#endif - } - else if(!mapArgs.count("-conf")) { - sprintf(confname,"%s.conf",symbol); - komodo_statefname(fname,symbol,confname); - } else sprintf(fname,"%s",GetDataDir().string().c_str()); - - if ( (fp= fopen(fname,"rb")) != 0 ) - { - port = _komodo_userpass(username,password,fp); - sprintf(userpass,"%s:%s",username,password); - if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 ) - strcpy(ASSETCHAINS_USERPASS,userpass); - fclose(fp); - } - return(port); -} +uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen); -uint32_t komodo_assetmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t extralen) -{ - uint8_t buf[512]; uint32_t crc0=0; int32_t len = 0; bits256 hash; - if ( strcmp(symbol,"KMD") == 0 ) - return(0x8de4eef9); - len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); - strcpy((char *)&buf[len],symbol); - len += strlen(symbol); - if ( extraptr != 0 && extralen != 0 ) - { - vcalc_sha256(0,hash.bytes,extraptr,extralen); - crc0 = hash.uints[0]; - int32_t i; for (i=0; i nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 ) - break; - } - } - if ( curEra <= ASSETCHAINS_LASTERA ) - { - int64_t nStart = curEra ? ASSETCHAINS_ENDSUBSIDY[curEra - 1] : 0; - subsidy = (int64_t)ASSETCHAINS_REWARD[curEra]; - if ( subsidy || (curEra != ASSETCHAINS_LASTERA && ASSETCHAINS_REWARD[curEra + 1] != 0) ) - { - if ( ASSETCHAINS_HALVING[curEra] != 0 ) - { - if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) - { - if ( ASSETCHAINS_DECAY[curEra] == 0 ) - subsidy >>= numhalvings; - else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) - { - if ( curEra == ASSETCHAINS_LASTERA ) - { - subsidyDifference = subsidy; - } - else - { - // Ex: -ac_eras=3 -ac_reward=0,384,24 -ac_end=1440,260640,0 -ac_halving=1,1440,2103840 -ac_decay 100000000,97750000,0 - subsidyDifference = subsidy - ASSETCHAINS_REWARD[curEra + 1]; - if (subsidyDifference < 0) - { - sign = -1; - subsidyDifference *= sign; - } - } - denominator = ASSETCHAINS_ENDSUBSIDY[curEra] - nStart; - numerator = denominator - ((ASSETCHAINS_ENDSUBSIDY[curEra] - nHeight) + ((nHeight - nStart) % ASSETCHAINS_HALVING[curEra])); - subsidy = subsidy - sign * ((subsidyDifference * numerator) / denominator); - } - else - { - if ( cached_subsidy > 0 && cached_era == curEra && cached_numhalvings == numhalvings ) - subsidy = cached_subsidy; - else - { - for (int i=0; i < numhalvings && subsidy != 0; i++) - subsidy = (subsidy * ASSETCHAINS_DECAY[curEra]) / 100000000; - cached_subsidy = subsidy; - cached_numhalvings = numhalvings; - cached_era = curEra; - } - } - } - } - } - } - } - uint32_t magicExtra = ASSETCHAINS_STAKED ? ASSETCHAINS_MAGIC : (ASSETCHAINS_MAGIC & 0xffffff); - if ( ASSETCHAINS_SUPPLY > 10000000000 ) // over 10 billion? - { - if ( nHeight <= ASSETCHAINS_SUPPLY/1000000000 ) - { - subsidy += (uint64_t)1000000000 * COIN; - if ( nHeight == 1 ) - subsidy += (ASSETCHAINS_SUPPLY % 1000000000)*COIN + magicExtra; - } - } - else if ( nHeight == 1 ) - { - if ( ASSETCHAINS_LASTERA == 0 ) - subsidy = ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; - else - subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra; - } - else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 ) - return(0); - // LABS fungible chains, cannot have any block reward! - return(subsidy); -} - -extern int64_t MAX_MONEY; -void komodo_cbopretupdate(int32_t forceflag); -void SplitStr(const std::string& strVal, std::vector &outVals); - -int8_t equihash_params_possible(uint64_t n, uint64_t k) -{ - /* To add more of these you also need to edit: - * equihash.cpp very end of file with the tempate to point to the new param numbers - * equihash.h - * line 210/217 (declaration of equihash class) - * Add this object to the following functions: - * EhInitialiseState - * EhBasicSolve - * EhOptimisedSolve - * EhIsValidSolution - * Alternatively change ASSETCHAINS_N and ASSETCHAINS_K in komodo_nk.h for fast testing. - */ - if ( k == 9 && (n == 200 || n == 210) ) - return(0); - if ( k == 5 && (n == 150 || n == 144 || n == 96 || n == 48) ) - return(0); - if ( k == ASSETCHAINS_K && n == ASSETCHAINS_N) - return(0); - return(-1); -} - -void komodo_args(char *argv0) -{ - std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; - FILE *fp; uint64_t val; uint16_t port, dest_rpc_port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; - - std::string ntz_dest_path; - ntz_dest_path = GetArg("-notary", ""); - IS_KOMODO_NOTARY = ntz_dest_path == "" ? 0 : 1; - - - IS_STAKED_NOTARY = GetArg("-stakednotary", -1); - KOMODO_NSPV = GetArg("-nSPV",0); - memset(ccenables,0,sizeof(ccenables)); - memset(disablebits,0,sizeof(disablebits)); - memset(ccEnablesHeight,0,sizeof(ccEnablesHeight)); - if ( GetBoolArg("-gen", false) != 0 ) - { - KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); - } - if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 ) - fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n"); - DONATION_PUBKEY = GetArg("-donation", ""); - NOTARY_PUBKEY = GetArg("-pubkey", ""); - KOMODO_DEALERNODE = GetArg("-dealer",0); - KOMODO_TESTNODE = GetArg("-testnode",0); - ASSETCHAINS_STAKED_SPLIT_PERCENTAGE = GetArg("-splitperc",0); - if ( strlen(NOTARY_PUBKEY.c_str()) == 66 ) - { - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); - USE_EXTERNAL_PUBKEY = 1; - if ( IS_KOMODO_NOTARY == 0 ) - { - // We dont have any chain data yet, so use system clock to guess. - // I think on season change should reccomend notaries to use -notary to avoid needing this. - int32_t kmd_season = getacseason(time(NULL)); - for (i=0; i<64; i++) - { - if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_elected[kmd_season-1][i][1]) == 0 ) - { - IS_KOMODO_NOTARY = 1; - KOMODO_MININGTHREADS = 1; - mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS); - IS_STAKED_NOTARY = -1; - fprintf(stderr,"running as notary.%d %s\n",i,notaries_elected[kmd_season-1][i][0]); - break; - } - } - } - } - if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) { - fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n"); - StartShutdown(); - } - name = GetArg("-ac_name",""); - if ( argv0 != 0 ) - { - len = (int32_t)strlen(argv0); - for (i=0; i matches suffix (%s) -> ac_name.(%s)\n",argv0,argv0suffix[i],argv0names[i]); - name = argv0names[i]; - break; - } - } - } - KOMODO_STOPAT = GetArg("-stopat",0); - MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); - WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; - ASSETCHAINS_CC = GetArg("-ac_cc",0); - KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0); - ASSETCHAINS_BLOCKTIME = GetArg("-ac_blocktime",60); - ASSETCHAINS_PUBLIC = GetArg("-ac_public",0); - ASSETCHAINS_PRIVATE = GetArg("-ac_private",0); - KOMODO_SNAPSHOT_INTERVAL = GetArg("-ac_snapshot",0); - Split(GetArg("-ac_nk",""), sizeof(ASSETCHAINS_NK)/sizeof(*ASSETCHAINS_NK), ASSETCHAINS_NK, 0); - - // -ac_ccactivateht=evalcode,height,evalcode,height,evalcode,height.... - Split(GetArg("-ac_ccactivateht",""), sizeof(ccEnablesHeight)/sizeof(*ccEnablesHeight), ccEnablesHeight, 0); - // fill map with all eval codes and activation height of 0. - for ( int i = 0; i < 256; i++ ) - mapHeightEvalActivate[i] = 0; - for ( int i = 0; i < 512; i++ ) - { - int32_t ecode = ccEnablesHeight[i]; - int32_t ht = ccEnablesHeight[i+1]; - if ( i > 1 && ccEnablesHeight[i-2] == ecode ) - break; - if ( ecode > 255 || ecode < 0 ) - fprintf(stderr, "ac_ccactivateht: invalid evalcode.%i must be between 0 and 256.\n", ecode); - else if ( ht > 0 ) - { - // update global map. - mapHeightEvalActivate[ecode] = ht; - fprintf(stderr, "ac_ccactivateht: ecode.%i activates at height.%i\n", ecode, mapHeightEvalActivate[ecode]); - } - i++; - } - - if ( (KOMODO_REWIND= GetArg("-rewind",0)) != 0 ) - { - printf("KOMODO_REWIND %d\n",KOMODO_REWIND); - } - KOMODO_EARLYTXID = Parseuint256(GetArg("-earlytxid","0").c_str()); - ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0); - if ( name.c_str()[0] != 0 ) - { - std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0])); - - for ( int i = 0; i < ASSETCHAINS_NUMALGOS; i++ ) - { - if (std::string(ASSETCHAINS_ALGORITHMS[i]) == selectedAlgo) - { - ASSETCHAINS_ALGO = i; - STAKING_MIN_DIFF = ASSETCHAINS_MINDIFF[i]; - // only worth mentioning if it's not equihash - if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH) - printf("ASSETCHAINS_ALGO, algorithm set to %s\n", selectedAlgo.c_str()); - break; - } - } - if ( ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH && ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0 ) - { - if ( equihash_params_possible(ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]) == -1 ) - { - printf("equihash values N.%li and K.%li are not currently available\n", ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]); - exit(0); - } else printf("ASSETCHAINS_ALGO, algorithm set to equihash with N.%li and K.%li\n", ASSETCHAINS_NK[0], ASSETCHAINS_NK[1]); - } - if (i == ASSETCHAINS_NUMALGOS) - { - printf("ASSETCHAINS_ALGO, %s not supported. using equihash\n", selectedAlgo.c_str()); - } - - ASSETCHAINS_LASTERA = GetArg("-ac_eras", 1); - if ( ASSETCHAINS_LASTERA < 1 || ASSETCHAINS_LASTERA > ASSETCHAINS_MAX_ERAS ) - { - ASSETCHAINS_LASTERA = 1; - printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %lu\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA); - } - ASSETCHAINS_LASTERA -= 1; - - ASSETCHAINS_TIMELOCKGTE = (uint64_t)GetArg("-ac_timelockgte", _ASSETCHAINS_TIMELOCKOFF); - ASSETCHAINS_TIMEUNLOCKFROM = GetArg("-ac_timeunlockfrom", 0); - ASSETCHAINS_TIMEUNLOCKTO = GetArg("-ac_timeunlockto", 0); - if ( ASSETCHAINS_TIMEUNLOCKFROM > ASSETCHAINS_TIMEUNLOCKTO ) - { - printf("ASSETCHAINS_TIMELOCKGTE - must specify valid ac_timeunlockfrom and ac_timeunlockto\n"); - ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF; - ASSETCHAINS_TIMEUNLOCKFROM = ASSETCHAINS_TIMEUNLOCKTO = 0; - } - - Split(GetArg("-ac_end",""), sizeof(ASSETCHAINS_ENDSUBSIDY)/sizeof(*ASSETCHAINS_ENDSUBSIDY), ASSETCHAINS_ENDSUBSIDY, 0); - Split(GetArg("-ac_reward",""), sizeof(ASSETCHAINS_REWARD)/sizeof(*ASSETCHAINS_REWARD), ASSETCHAINS_REWARD, 0); - Split(GetArg("-ac_halving",""), sizeof(ASSETCHAINS_HALVING)/sizeof(*ASSETCHAINS_HALVING), ASSETCHAINS_HALVING, 0); - Split(GetArg("-ac_decay",""), sizeof(ASSETCHAINS_DECAY)/sizeof(*ASSETCHAINS_DECAY), ASSETCHAINS_DECAY, 0); - Split(GetArg("-ac_notarypay",""), sizeof(ASSETCHAINS_NOTARY_PAY)/sizeof(*ASSETCHAINS_NOTARY_PAY), ASSETCHAINS_NOTARY_PAY, 0); - - for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ ) - { - if ( ASSETCHAINS_DECAY[i] == 100000000 && ASSETCHAINS_ENDSUBSIDY == 0 ) - { - ASSETCHAINS_DECAY[i] = 0; - printf("ERA%u: ASSETCHAINS_DECAY of 100000000 means linear and that needs ASSETCHAINS_ENDSUBSIDY\n", i); - } - else if ( ASSETCHAINS_DECAY[i] > 100000000 ) - { - ASSETCHAINS_DECAY[i] = 0; - printf("ERA%u: ASSETCHAINS_DECAY cant be more than 100000000\n", i); - } - } - - MAX_BLOCK_SIGOPS = 60000; - ASSETCHAINS_TXPOW = GetArg("-ac_txpow",0) & 3; - ASSETCHAINS_FOUNDERS = GetArg("-ac_founders",0);// & 1; - ASSETCHAINS_FOUNDERS_REWARD = GetArg("-ac_founders_reward",0); - ASSETCHAINS_SUPPLY = GetArg("-ac_supply",10); - if ( ASSETCHAINS_SUPPLY > (uint64_t)90*1000*1000000 ) - { - fprintf(stderr,"-ac_supply must be less than 90 billion\n"); - StartShutdown(); - } - fprintf(stderr,"ASSETCHAINS_SUPPLY %llu\n",(long long)ASSETCHAINS_SUPPLY); - - ASSETCHAINS_COMMISSION = GetArg("-ac_perc",0); - ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey",""); - ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); - ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); - ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); - ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0); - ASSETCHAINS_CBOPRET = GetArg("-ac_cbopret",0); - ASSETCHAINS_CBMATURITY = GetArg("-ac_cbmaturity",0); - ASSETCHAINS_ADAPTIVEPOW = GetArg("-ac_adaptivepow",0); - //fprintf(stderr,"ASSETCHAINS_CBOPRET.%llx\n",(long long)ASSETCHAINS_CBOPRET); - if ( ASSETCHAINS_CBOPRET != 0 ) - { - SplitStr(GetArg("-ac_prices",""), ASSETCHAINS_PRICES); - if ( ASSETCHAINS_PRICES.size() > 0 ) - ASSETCHAINS_CBOPRET |= 4; - SplitStr(GetArg("-ac_stocks",""), ASSETCHAINS_STOCKS); - if ( ASSETCHAINS_STOCKS.size() > 0 ) - ASSETCHAINS_CBOPRET |= 8; - for (i=0; i 0 ) - { - for (i=0; i<256; i++) - { - ASSETCHAINS_CCDISABLES[i] = 1; - SETBIT(disablebits,i); - } - for (i=0; i 0 ) - { - for (i=first; i<=last; i++) - { - CLEARBIT(disablebits,i); - ASSETCHAINS_CCDISABLES[i] = 0; - } - }*/ - } - if ( ASSETCHAINS_BEAMPORT != 0 ) - { - fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n"); - StartShutdown(); - } - ASSETCHAINS_SELFIMPORT = GetArg("-ac_import",""); // BEAM, CODA, PUBKEY, GATEWAY - if ( ASSETCHAINS_SELFIMPORT == "PUBKEY" ) - { - if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) != 66 ) - { - fprintf(stderr,"invalid -ac_pubkey for -ac_import=PUBKEY\n"); - StartShutdown(); - } - } - else if ( ASSETCHAINS_SELFIMPORT == "BEAM" ) - { - if (ASSETCHAINS_BEAMPORT == 0) - { - fprintf(stderr,"missing -ac_beam for BEAM rpcport\n"); - StartShutdown(); - } - } - else if ( ASSETCHAINS_SELFIMPORT == "CODA" ) - { - if (ASSETCHAINS_CODAPORT == 0) - { - fprintf(stderr,"missing -ac_coda for CODA rpcport\n"); - StartShutdown(); - } - } - else if ( ASSETCHAINS_SELFIMPORT == "PEGSCC") - { - Split(GetArg("-ac_pegsccparams",""), sizeof(ASSETCHAINS_PEGSCCPARAMS)/sizeof(*ASSETCHAINS_PEGSCCPARAMS), ASSETCHAINS_PEGSCCPARAMS, 0); - if (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_COMMISSION!=0) - { - fprintf(stderr,"when using import for pegsCC these must be set: -ac_end=1 -ac_perc=0\n"); - StartShutdown(); - } - } - // else it can be gateway coin - else if (!ASSETCHAINS_SELFIMPORT.empty() && (ASSETCHAINS_ENDSUBSIDY[0]!=1 || ASSETCHAINS_SUPPLY>0 || ASSETCHAINS_COMMISSION!=0)) - { - fprintf(stderr,"when using gateway import these must be set: -ac_end=1 -ac_supply=0 -ac_perc=0\n"); - StartShutdown(); - } - - - if ( (ASSETCHAINS_STAKED= GetArg("-ac_staked",0)) > 100 ) - ASSETCHAINS_STAKED = 100; - - // for now, we only support 50% PoS due to other parts of the algorithm needing adjustment for - // other values - if ( (ASSETCHAINS_LWMAPOS = GetArg("-ac_veruspos",0)) != 0 ) - { - ASSETCHAINS_LWMAPOS = 50; - } - ASSETCHAINS_SAPLING = GetArg("-ac_sapling", -1); - if (ASSETCHAINS_SAPLING == -1) - { - ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", -1); - } - else - { - ASSETCHAINS_OVERWINTER = GetArg("-ac_overwinter", ASSETCHAINS_SAPLING); - } - if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 || ASSETCHAINS_SCRIPTPUB.size() > 1 ) - { - if ( ASSETCHAINS_SUPPLY > 10000000000 ) - { - printf("ac_pubkey or ac_script wont work with ac_supply over 10 billion\n"); - StartShutdown(); - } - if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) - { - printf("Assetchains NOTARY PAY cannot be used with ac_pubkey or ac_script.\n"); - StartShutdown(); - } - if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 ) - { - decode_hex(ASSETCHAINS_OVERRIDE_PUBKEY33,33,(char *)ASSETCHAINS_OVERRIDE_PUBKEY.c_str()); - calc_rmd160_sha256(ASSETCHAINS_OVERRIDE_PUBKEYHASH,ASSETCHAINS_OVERRIDE_PUBKEY33,33); - } - if ( ASSETCHAINS_COMMISSION == 0 && ASSETCHAINS_FOUNDERS != 0 ) - { - if ( ASSETCHAINS_FOUNDERS_REWARD == 0 ) - { - ASSETCHAINS_COMMISSION = 53846154; // maps to 35% - printf("ASSETCHAINS_COMMISSION defaulted to 35%% when founders reward active\n"); - } - else - { - printf("ASSETCHAINS_FOUNDERS_REWARD set to %ld\n", ASSETCHAINS_FOUNDERS_REWARD); - } - /*else if ( ASSETCHAINS_SELFIMPORT.size() == 0 ) - { - //ASSETCHAINS_OVERRIDE_PUBKEY.clear(); - printf("-ac_perc must be set with -ac_pubkey\n"); - }*/ - } - } - else - { - if ( ASSETCHAINS_COMMISSION != 0 ) - { - ASSETCHAINS_COMMISSION = 0; - printf("ASSETCHAINS_COMMISSION needs an ASSETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n"); - } - if ( ASSETCHAINS_FOUNDERS != 0 ) - { - ASSETCHAINS_FOUNDERS = 0; - printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n"); - } - } - if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_MARMARA != 0 ) - { - fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n"); - StartShutdown(); - } - if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 ) - { - fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); - extraptr = extrabuf; - memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; - - // if we have one era, this should create the same data structure as it used to, same if we increase _MAX_ERAS - for ( int i = 0; i <= ASSETCHAINS_LASTERA; i++ ) - { - printf("ERA%u: end.%llu reward.%llu halving.%llu decay.%llu notarypay.%llu\n", i, - (long long)ASSETCHAINS_ENDSUBSIDY[i], - (long long)ASSETCHAINS_REWARD[i], - (long long)ASSETCHAINS_HALVING[i], - (long long)ASSETCHAINS_DECAY[i], - (long long)ASSETCHAINS_NOTARY_PAY[i]); - - // TODO: Verify that we don't overrun extrabuf here, which is a 256 byte buffer - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ENDSUBSIDY[i]),(void *)&ASSETCHAINS_ENDSUBSIDY[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD[i]),(void *)&ASSETCHAINS_REWARD[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING[i]),(void *)&ASSETCHAINS_HALVING[i]); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY[i]),(void *)&ASSETCHAINS_DECAY[i]); - if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NOTARY_PAY[i]),(void *)&ASSETCHAINS_NOTARY_PAY[i]); - } - - if (ASSETCHAINS_LASTERA > 0) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LASTERA),(void *)&ASSETCHAINS_LASTERA); - } - - // hash in lock above for time locked coinbase transactions above a certain reward value only if the lock above - // param was specified, otherwise, for compatibility, do nothing - if ( ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF ) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMELOCKGTE),(void *)&ASSETCHAINS_TIMELOCKGTE); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKFROM),(void *)&ASSETCHAINS_TIMEUNLOCKFROM); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_TIMEUNLOCKTO),(void *)&ASSETCHAINS_TIMEUNLOCKTO); - } - - if ( ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH ) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); - } - - if ( ASSETCHAINS_LWMAPOS != 0 ) - { - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS); - } - - val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); - - if ( ASSETCHAINS_FOUNDERS != 0 ) - { - uint8_t tmp = 1; - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(tmp),(void *)&tmp); - if ( ASSETCHAINS_FOUNDERS > 1 ) - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS); - if ( ASSETCHAINS_FOUNDERS_REWARD != 0 ) - { - fprintf(stderr, "set founders reward.%lld\n",(long long)ASSETCHAINS_FOUNDERS_REWARD); - extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD); - } - } - if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) - { - decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); - extralen += ASSETCHAINS_SCRIPTPUB.size()/2; - //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); - fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); - } - if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) - { - memcpy(&extraptr[extralen],(char *)ASSETCHAINS_SELFIMPORT.c_str(),ASSETCHAINS_SELFIMPORT.size()); - for (i=0; i 0 ) - { - memcpy(&extraptr[extralen],disablebits,sizeof(disablebits)); - extralen += sizeof(disablebits); - } - if ( ASSETCHAINS_CCLIB.size() > 1 ) - { - for (i=0; i 0 ) - ASSETCHAINS_SEED = 1; - - strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); - - MAX_MONEY = komodo_max_money(); - - if ( (baseid = komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) - { - //komodo_maxallowed(baseid); - printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); - } - - if ( ASSETCHAINS_CC >= KOMODO_FIRSTFUNGIBLEID && MAX_MONEY < 1000000LL*SATOSHIDEN ) - MAX_MONEY = 1000000LL*SATOSHIDEN; - if ( KOMODO_BIT63SET(MAX_MONEY) != 0 ) - MAX_MONEY = KOMODO_MAXNVALUE; - fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); - //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); - uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); - if ( GetArg("-port",0) != 0 ) - { - ASSETCHAINS_P2PPORT = GetArg("-port",0); - fprintf(stderr,"set p2pport.%u\n",ASSETCHAINS_P2PPORT); - } else ASSETCHAINS_P2PPORT = tmpport; - - while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) - { - fprintf(stderr,"waiting for datadir (%s)\n",dirname); -#ifndef _WIN32 - sleep(3); -#else - boost::this_thread::sleep(boost::posix_time::milliseconds(3000)); -#endif - } - //fprintf(stderr,"Got datadir.(%s)\n",dirname); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - int32_t komodo_baseid(char *origbase); - extern int COINBASE_MATURITY; - if ( strcmp(ASSETCHAINS_SYMBOL,"KMD") == 0 ) - { - fprintf(stderr,"cant have assetchain named KMD\n"); - StartShutdown(); - } - if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) - ASSETCHAINS_RPCPORT = port; - else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); - - if (ASSETCHAINS_CBMATURITY != 0) - COINBASE_MATURITY = ASSETCHAINS_CBMATURITY; - else if (ASSETCHAINS_LASTERA == 0 || is_STAKED(ASSETCHAINS_SYMBOL) != 0) - COINBASE_MATURITY = 1; - if (COINBASE_MATURITY < 1) - { - fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); - StartShutdown(); - } - //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); - } - if ( ASSETCHAINS_RPCPORT == 0 ) - ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; - //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); - //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); - iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); - for (i=0; i<4; i++) - sprintf(&magicstr[i<<1],"%02x",magic[i]); - magicstr[8] = 0; -#ifndef FROM_CLI - sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); - if ( (fp= fopen(fname,"wb")) != 0 ) - { - int8_t notarypay = 0; - if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) - notarypay = 1; - fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146",notarypay); - fclose(fp); - //printf("created (%s)\n",fname); - } else printf("error creating (%s)\n",fname); -#endif - if ( ASSETCHAINS_CC < 2 ) - { - if ( KOMODO_CCACTIVATE != 0 ) - { - ASSETCHAINS_CC = 2; - fprintf(stderr,"smart utxo CC contracts will activate at height.%d\n",KOMODO_CCACTIVATE); - } - else if ( ccEnablesHeight[0] != 0 ) - { - ASSETCHAINS_CC = 2; - fprintf(stderr,"smart utxo CC contract %d will activate at height.%d\n",(int32_t)ccEnablesHeight[0],(int32_t)ccEnablesHeight[1]); - } - } - } - else - { - char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; - ASSETCHAINS_P2PPORT = 7770; - ASSETCHAINS_RPCPORT = 7771; - for (iter=0; iter<2; iter++) - { - strcpy(fname,GetDataDir().string().c_str()); -#ifdef _WIN32 - while ( fname[strlen(fname)-1] != '\\' ) - fname[strlen(fname)-1] = 0; - if ( iter == 0 ) - strcat(fname,"Komodo\\komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#else - while ( fname[strlen(fname)-1] != '/' ) - fname[strlen(fname)-1] = 0; -#ifdef __APPLE__ - if ( iter == 0 ) - strcat(fname,"Komodo/Komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#else - if ( iter == 0 ) - strcat(fname,".komodo/komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#endif -#endif - if ( (fp= fopen(fname,"rb")) != 0 ) - { - dest_rpc_port = _komodo_userpass(username,password,fp); - DEST_PORT = iter == 1 ? dest_rpc_port : 0; - sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); - fclose(fp); - } else printf("couldnt open.(%s) will not validate dest notarizations\n",fname); - if ( IS_KOMODO_NOTARY == 0 ) - break; - } - } - int32_t dpowconfs = KOMODO_DPOWCONFS; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); - //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); - if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) - { - ASSETCHAINS_HALVING[0] *= 5; - fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%llu\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,(long long)ASSETCHAINS_LASTERA); - } - else if ( strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 ) - dpowconfs = 0; - else if ( ASSETCHAINS_PRIVATE != 0 ) - { - fprintf(stderr,"-ac_private for a non-PIRATE chain is not supported. The only reason to have an -ac_private chain is for total privacy and that is best achieved with the largest anon set. PIRATE has that and it is recommended to just use PIRATE\n"); - StartShutdown(); - } - // Set cc enables for all existing ac_cc chains here. - if ( strcmp("AXO",ASSETCHAINS_SYMBOL) == 0 ) - { - // No CCs used on this chain yet. - CCDISABLEALL; - } - if ( strcmp("CCL",ASSETCHAINS_SYMBOL) == 0 ) - { - // No CCs used on this chain yet. - CCDISABLEALL; - CCENABLE(EVAL_TOKENS); - CCENABLE(EVAL_HEIR); - } - if ( strcmp("COQUI",ASSETCHAINS_SYMBOL) == 0 ) - { - CCDISABLEALL; - CCENABLE(EVAL_DICE); - CCENABLE(EVAL_CHANNELS); - CCENABLE(EVAL_ORACLES); - CCENABLE(EVAL_ASSETS); - CCENABLE(EVAL_TOKENS); - } - if ( strcmp("DION",ASSETCHAINS_SYMBOL) == 0 ) - { - // No CCs used on this chain yet. - CCDISABLEALL; - } - - if ( strcmp("EQL",ASSETCHAINS_SYMBOL) == 0 ) - { - // No CCs used on this chain yet. - CCDISABLEALL; - } - if ( strcmp("ILN",ASSETCHAINS_SYMBOL) == 0 ) - { - // No CCs used on this chain yet. - CCDISABLEALL; - } - if ( strcmp("OUR",ASSETCHAINS_SYMBOL) == 0 ) - { - // No CCs used on this chain yet. - CCDISABLEALL; - } - if ( strcmp("ZEXO",ASSETCHAINS_SYMBOL) == 0 ) - { - // No CCs used on this chain yet. - CCDISABLEALL; - } - if ( strcmp("SEC",ASSETCHAINS_SYMBOL) == 0 ) - { - CCDISABLEALL; - CCENABLE(EVAL_ASSETS); - CCENABLE(EVAL_TOKENS); - CCENABLE(EVAL_ORACLES); - } - if ( strcmp("KMDICE",ASSETCHAINS_SYMBOL) == 0 ) - { - CCDISABLEALL; - CCENABLE(EVAL_FAUCET); - CCENABLE(EVAL_DICE); - CCENABLE(EVAL_ORACLES); - } - } else BITCOIND_RPCPORT = GetArg("-rpcport", BaseParams().RPCPort()); - KOMODO_DPOWCONFS = GetArg("-dpowconfs",dpowconfs); - if ( ASSETCHAINS_SYMBOL[0] == 0 || strcmp(ASSETCHAINS_SYMBOL,"SUPERNET") == 0 || strcmp(ASSETCHAINS_SYMBOL,"DEX") == 0 || strcmp(ASSETCHAINS_SYMBOL,"COQUI") == 0 || strcmp(ASSETCHAINS_SYMBOL,"PIRATE") == 0 || strcmp(ASSETCHAINS_SYMBOL,"KMDICE") == 0 ) - KOMODO_EXTRASATOSHI = 1; -} - -void komodo_nameset(char *symbol,char *dest,char *source) -{ - if ( source[0] == 0 ) - { - strcpy(symbol,(char *)"KMD"); - strcpy(dest,(char *)"BTC"); - } - else - { - strcpy(symbol,source); - strcpy(dest,(char *)"KMD"); - } -} - -struct komodo_state *komodo_stateptrget(char *base) -{ - int32_t baseid; - if ( base == 0 || base[0] == 0 || strcmp(base,(char *)"KMD") == 0 ) - return(&KOMODO_STATES[33]); - else if ( (baseid= komodo_baseid(base)) >= 0 ) - return(&KOMODO_STATES[baseid+1]); - else return(&KOMODO_STATES[0]); -} - -struct komodo_state *komodo_stateptr(char *symbol,char *dest) -{ - int32_t baseid; - komodo_nameset(symbol,dest,ASSETCHAINS_SYMBOL); - return(komodo_stateptrget(symbol)); -} - -void komodo_prefetch(FILE *fp) -{ - long fsize,fpos; int32_t incr = 16*1024*1024; - fpos = ftell(fp); - fseek(fp,0,SEEK_END); - fsize = ftell(fp); - if ( fsize > incr ) - { - char *ignore = (char *)malloc(incr); - if ( ignore != 0 ) - { - rewind(fp); - while ( fread(ignore,1,incr,fp) == incr ) // prefetch - fprintf(stderr,"."); - free(ignore); - } - } - fseek(fp,fpos,SEEK_SET); -} +void komodo_prefetch(FILE *fp); // check if block timestamp is more than S5 activation time // this function is to activate the ExtractDestination fix -bool komodo_is_vSolutionsFixActive() -{ - return GetLatestTimestamp(komodo_currentheight()) > nS5Timestamp; -} +bool komodo_is_vSolutionsFixActive(); diff --git a/src/main.cpp b/src/main.cpp index 7d0d52424ed..783280cdea6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -646,7 +646,6 @@ CBlockTreeDB *pblocktree = NULL; // Komodo globals -#define KOMODO_ZCASH #include "komodo.h" UniValue komodo_snapshot(int top) diff --git a/src/primitives/nonce.h b/src/primitives/nonce.h index 605564671d2..39ee445e02c 100644 --- a/src/primitives/nonce.h +++ b/src/primitives/nonce.h @@ -23,7 +23,7 @@ #include "serialize.h" #include "uint256.h" #include "arith_uint256.h" - +#include "hash.h" // CVerusHashWriter /** For POS blocks, the nNonce of a block header holds the entropy source for the POS contest * in the latest VerusHash protocol diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1416d3bc72d..f30cfaa7929 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -495,17 +495,6 @@ static const CRPCCommand vRPCCommands[] = // Pegs { "pegs", "pegsaddress", &pegsaddress, true }, - // Marmara - { "marmara", "marmaraaddress", &marmaraaddress, true }, - { "marmara", "marmarapoolpayout", &marmara_poolpayout, true }, - { "marmara", "marmarareceive", &marmara_receive, true }, - { "marmara", "marmaraissue", &marmara_issue, true }, - { "marmara", "marmaratransfer", &marmara_transfer, true }, - { "marmara", "marmarainfo", &marmara_info, true }, - { "marmara", "marmaracreditloop", &marmara_creditloop, true }, - { "marmara", "marmarasettlement", &marmara_settlement, true }, - { "marmara", "marmaralock", &marmara_lock, true }, - // Payments { "payments", "paymentsaddress", &paymentsaddress, true }, { "payments", "paymentstxidopret", &payments_txidopret, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 465bc832b56..1484f56d5c4 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -279,15 +279,6 @@ extern UniValue priceslist(const UniValue& params, bool fHelp, const CPubKey& my extern UniValue mypriceslist(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue pricesinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue pegsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmaraaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_poolpayout(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_receive(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_issue(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_transfer(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_info(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_creditloop(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_settlement(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue marmara_lock(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue paymentsaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue payments_release(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue payments_fund(const UniValue& params, bool fHelp, const CPubKey& mypk); @@ -298,7 +289,6 @@ extern UniValue payments_airdrop(const UniValue& params, bool fHelp, const CPubK extern UniValue payments_airdroptokens(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue payments_info(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue payments_list(const UniValue& params, bool fHelp, const CPubKey& mypk); - extern UniValue cclibaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue cclibinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue cclib(const UniValue& params, bool fHelp, const CPubKey& mypk); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e2c1cb86a04..c83d7f59707 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6240,192 +6240,6 @@ UniValue importgatewayaddress(const UniValue& params, bool fHelp, const CPubKey& return(CCaddress(cp,(char *)"ImportGateway", pubkey)); } -UniValue marmara_poolpayout(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - int32_t firstheight; double perc; char *jsonstr; - if ( fHelp || params.size() != 3 ) - { - // marmarapoolpayout 0.5 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000],["02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92",100]]'; - //marmarapoolpayout 0 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000]]' - throw runtime_error("marmarapoolpayout perc firstheight \"[[\\\"pubkey\\\":shares], ...]\"\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - perc = atof(params[0].get_str().c_str()) / 100.; - firstheight = atol(params[1].get_str().c_str()); - jsonstr = (char *)params[2].get_str().c_str(); - return(MarmaraPoolPayout(0,firstheight,perc,jsonstr)); // [[pk0, shares0], [pk1, shares1], ...] -} - -UniValue marmara_receive(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 batontxid; std::vector senderpub; int64_t amount; int32_t matures; std::string currency; - if ( fHelp || (params.size() != 5 && params.size() != 4) ) - { - // automatic flag -> lsb of matures - // 1st marmarareceive 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1440 - // after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 d72d87aa0d50436de695c93e2bf3d7273c63c92ef6307913aa01a6ee6a16548b - throw runtime_error("marmarareceive senderpk amount currency matures batontxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - memset(&batontxid,0,sizeof(batontxid)); - senderpub = ParseHex(params[0].get_str().c_str()); - if (senderpub.size()!= 33) - { - ERR_RESULT("invalid sender pubkey"); - return result; - } - amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; - currency = params[2].get_str(); - if ( params.size() == 5 ) - { - matures = atol(params[3].get_str().c_str()); - batontxid = Parseuint256((char *)params[4].get_str().c_str()); - } else matures = atol(params[3].get_str().c_str()) + chainActive.LastTip()->GetHeight() + 1; - return(MarmaraReceive(0,pubkey2pk(senderpub),amount,currency,matures,batontxid,true)); -} - -UniValue marmara_issue(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 approvaltxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; - if ( fHelp || params.size() != 5 ) - { - // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 32da4cb3e886ee42de90b4a15042d71169077306badf909099c5c5c692df3f27 - // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 700 MARMARA 2629 11fe8bf1de80c2ef69124d08907f259aef7f41e3a632ca2d48ad072a8c8f3078 -> 335df3a5dd6b92a3d020c9465d4d76e0d8242126106b83756dcecbad9813fdf3 - - throw runtime_error("marmaraissue receiverpk amount currency matures approvaltxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - receiverpub = ParseHex(params[0].get_str().c_str()); - if (receiverpub.size()!= 33) - { - ERR_RESULT("invalid receiverpub pubkey"); - return result; - } - amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; - currency = params[2].get_str(); - matures = atol(params[3].get_str().c_str()); - approvaltxid = Parseuint256((char *)params[4].get_str().c_str()); - return(MarmaraIssue(0,'I',pubkey2pk(receiverpub),amount,currency,matures,approvaltxid,zeroid)); -} - -UniValue marmara_transfer(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 approvaltxid,batontxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; std::vector creditloop; - if ( fHelp || params.size() != 5 ) - { - // marmaratransfer 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1168 1506c774e4b2804a6e25260920840f4cfca8d1fb400e69fe6b74b8e593dbedc5 - throw runtime_error("marmaratransfer receiverpk amount currency matures approvaltxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - receiverpub = ParseHex(params[0].get_str().c_str()); - if (receiverpub.size()!= 33) - { - ERR_RESULT("invalid receiverpub pubkey"); - return result; - } - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; - currency = params[2].get_str(); - matures = atol(params[3].get_str().c_str()); - approvaltxid = Parseuint256((char *)params[4].get_str().c_str()); - if ( MarmaraGetbatontxid(creditloop,batontxid,approvaltxid) < 0 ) - throw runtime_error("couldnt find batontxid\n"); - return(MarmaraIssue(0,'T',pubkey2pk(receiverpub),amount,currency,matures,approvaltxid,batontxid)); -} - -UniValue marmara_info(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); CPubKey issuerpk; std::vector issuerpub; int64_t minamount,maxamount; int32_t firstheight,lastheight; std::string currency; - if ( fHelp || params.size() < 4 || params.size() > 6 ) - { - throw runtime_error("marmarainfo firstheight lastheight minamount maxamount [currency issuerpk]\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - firstheight = atol(params[0].get_str().c_str()); - lastheight = atol(params[1].get_str().c_str()); - minamount = atof(params[2].get_str().c_str()) * COIN + 0.00000000499999; - maxamount = atof(params[3].get_str().c_str()) * COIN + 0.00000000499999; - if ( params.size() >= 5 ) - currency = params[4].get_str(); - if ( params.size() == 6 ) - { - issuerpub = ParseHex(params[5].get_str().c_str()); - if ( issuerpub.size()!= 33 ) - { - ERR_RESULT("invalid issuer pubkey"); - return result; - } - issuerpk = pubkey2pk(issuerpub); - } - result = MarmaraInfo(issuerpk,firstheight,lastheight,minamount,maxamount,currency); - return(result); -} - -UniValue marmara_creditloop(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 txid; - if ( fHelp || params.size() != 1 ) - { - // marmaracreditloop 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be - throw runtime_error("marmaracreditloop txid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - txid = Parseuint256((char *)params[0].get_str().c_str()); - result = MarmaraCreditloop(txid); - return(result); -} - -UniValue marmara_settlement(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); uint256 batontxid; - if ( fHelp || params.size() != 1 ) - { - // marmarasettlement 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be - // marmarasettlement ff3e259869196f3da9b5ea3f9e088a76c4fc063cf36ab586b652e121d441a603 - throw runtime_error("marmarasettlement batontxid\n"); - } - if ( ensure_CCrequirements(EVAL_MARMARA) < 0 ) - throw runtime_error(CC_REQUIREMENTS_MSG); - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - batontxid = Parseuint256((char *)params[0].get_str().c_str()); - result = MarmaraSettlement(0,batontxid); - return(result); -} - -UniValue marmara_lock(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - UniValue result(UniValue::VOBJ); int64_t amount; int32_t height; - if ( fHelp || params.size() > 2 || params.size() == 0 ) - { - throw runtime_error("marmaralock amount unlockht\n"); - } - const CKeyStore& keystore = *pwalletMain; - LOCK2(cs_main, pwalletMain->cs_wallet); - amount = atof(params[0].get_str().c_str()) * COIN + 0.00000000499999; - if ( params.size() == 2 ) - height = atol(params[1].get_str().c_str()); - else height = chainActive.LastTip()->GetHeight() + 1; - return(MarmaraLock(0,amount,height)); -} - UniValue channelslist(const UniValue& params, bool fHelp, const CPubKey& mypk) { if ( fHelp || params.size() > 0 ) From ea04faf2173c34216f7135ff5e92c9c028296e1b Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 1 Jun 2021 12:07:30 -0500 Subject: [PATCH 11/58] Tweaks for .cpp .h split --- src/komodo_curve25519.cpp | 13 +++++++++++++ src/komodo_curve25519.h | 2 -- src/komodo_cutils.cpp | 34 +++++++++++++++++++++++++++++++++- src/komodo_cutils.h | 4 ++++ src/komodo_utils.cpp | 31 ------------------------------- src/komodo_utils.h | 4 ---- 6 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/komodo_curve25519.cpp b/src/komodo_curve25519.cpp index 389fcd643a3..1b0dc7bb2bf 100644 --- a/src/komodo_curve25519.cpp +++ b/src/komodo_curve25519.cpp @@ -22,6 +22,19 @@ void store_limb(uint8_t *out,uint64_t in) out[i] = (in & 0xff); } +static inline uint64_t load_limb(uint8_t *in) +{ + return + ((uint64_t)in[0]) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16) | + (((uint64_t)in[3]) << 24) | + (((uint64_t)in[4]) << 32) | + (((uint64_t)in[5]) << 40) | + (((uint64_t)in[6]) << 48) | + (((uint64_t)in[7]) << 56); +} + // Take a little-endian, 32-byte number and expand it into polynomial form bits320 fexpand(bits256 basepoint) { diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index cfc631b9d3c..2405d6e6ea8 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -51,8 +51,6 @@ static inline void fdifference_backwards(uint64_t *out,const uint64_t *in) void store_limb(uint8_t *out,uint64_t in); -static inline uint64_t load_limb(uint8_t *in); - // Take a little-endian, 32-byte number and expand it into polynomial form bits320 fexpand(bits256 basepoint); diff --git a/src/komodo_cutils.cpp b/src/komodo_cutils.cpp index f0ca6887f96..74c9f6bcadc 100644 --- a/src/komodo_cutils.cpp +++ b/src/komodo_cutils.cpp @@ -1,4 +1,5 @@ #include "komodo_cutils.h" +#include "stdlib.h" //malloc int32_t _unhex(char c) { @@ -69,4 +70,35 @@ int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) } //bytes[i] = 0; return(n + adjust); -} \ No newline at end of file +} + +long _stripwhite(char *buf,int accept) +{ + int32_t i,j,c; + if ( buf == 0 || buf[0] == 0 ) + return(0); + for (i=j=0; buf[i]!=0; i++) + { + buf[j] = c = buf[i]; + if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) + j++; + } + buf[j] = 0; + return(j); +} + +char *clonestr(char *str) +{ + char *clone; + if ( str == 0 || str[0] == 0 ) + { + printf("warning cloning nullstr.%p\n",str); +#ifdef __APPLE__ + while ( 1 ) sleep(1); +#endif + str = (char *)""; + } + clone = (char *)malloc(strlen(str)+16); + strcpy(clone,str); + return(clone); +} diff --git a/src/komodo_cutils.h b/src/komodo_cutils.h index e1b1e7e04a2..ecb3b1effa9 100644 --- a/src/komodo_cutils.h +++ b/src/komodo_cutils.h @@ -16,3 +16,7 @@ int32_t unhex(char c); int32_t is_hexstr(char *str,int32_t n); int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); + +long _stripwhite(char *buf,int accept); + +char *clonestr(char *str); \ No newline at end of file diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index d270b39f6ae..d5c40da9cc6 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -761,37 +761,6 @@ int64_t komodo_block_unlocktime(uint32_t nHeight) return ((int64_t)unlocktime); } -long _stripwhite(char *buf,int accept) -{ - int32_t i,j,c; - if ( buf == 0 || buf[0] == 0 ) - return(0); - for (i=j=0; buf[i]!=0; i++) - { - buf[j] = c = buf[i]; - if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) - j++; - } - buf[j] = 0; - return(j); -} - -char *clonestr(char *str) -{ - char *clone; - if ( str == 0 || str[0] == 0 ) - { - printf("warning cloning nullstr.%p\n",str); -#ifdef __APPLE__ - while ( 1 ) sleep(1); -#endif - str = (char *)""; - } - clone = (char *)malloc(strlen(str)+16); - strcpy(clone,str); - return(clone); -} - int32_t safecopy(char *dest,char *src,long len) { int32_t i = -1; diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 4301cfd93c6..a4e5121b03a 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -341,10 +341,6 @@ uint64_t komodo_block_prg(uint32_t nHeight); // for corresponding blocks across chains, but the same sequence in each chain int64_t komodo_block_unlocktime(uint32_t nHeight); -long _stripwhite(char *buf,int accept); - -char *clonestr(char *str); - int32_t safecopy(char *dest,char *src,long len); char *parse_conf_line(char *line,char *field); From da28dc63d7f2c9eee42204a3640c0fd2a026e5d3 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 11 Jun 2021 09:36:05 -0500 Subject: [PATCH 12/58] move hex funcs to 1 place --- src/Makefile.am | 1 + src/bitcoind.cpp | 3 +- src/cc/CCcustom.cpp | 2 +- src/cc/CCinclude.h | 7 - src/cc/cclib.cpp | 3 +- src/cc/crypto777/OS_portable.h | 4 - src/cc/dapps/dappstd.c | 106 --------------- src/cc/dapps/oraclefeed.c | 102 --------------- src/cc/dapps/zmigrate.c | 102 --------------- src/cc/dice.cpp | 10 +- src/cc/faucet.cpp | 4 +- src/cc/marmara.cpp | 2 +- src/cc/payments.cpp | 2 +- src/cc/prices.cpp | 22 +--- src/cc/rogue/extern.h | 2 - src/cc/rogue/main.c | 106 --------------- src/chainparams.cpp | 2 +- src/hex.c | 143 ++++++++++++++++++++ src/hex.h | 70 ++++++++++ src/komodo.h | 28 +--- src/komodo_bitcoind.h | 36 +----- src/komodo_cJSON.c | 1 + src/komodo_defs.h | 11 +- src/komodo_events.h | 4 +- src/komodo_globals.h | 10 +- src/komodo_kv.h | 1 + src/komodo_nSPV_fullnode.h | 2 +- src/komodo_notary.h | 2 +- src/komodo_utils.h | 229 +++++++++++---------------------- src/main.cpp | 41 ++++-- src/miner.cpp | 21 +-- src/net.cpp | 5 - src/notaries_staked.cpp | 5 +- src/rpc/misc.cpp | 6 +- src/wallet-utility.cpp | 2 +- src/wallet/rpcwallet.cpp | 11 +- src/wallet/wallet.cpp | 40 +----- 37 files changed, 397 insertions(+), 751 deletions(-) create mode 100644 src/hex.c create mode 100644 src/hex.h diff --git a/src/Makefile.am b/src/Makefile.am index 23cff51cba9..eb8c5b8eb79 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -478,6 +478,7 @@ libbitcoin_common_a_SOURCES = \ crypto/verus_hash.h \ crypto/verus_hash.cpp \ hash.cpp \ + hex.c \ importcoin.cpp \ key.cpp \ key_io.cpp \ diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index ef7b09a37f0..a63e87129a3 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -108,7 +108,8 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // -extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY; +extern bool IS_KOMODO_NOTARY; +extern int32_t USE_EXTERNAL_PUBKEY; extern uint32_t ASSETCHAIN_INIT; extern std::string NOTARY_PUBKEY; int32_t komodo_is_issuer(); diff --git a/src/cc/CCcustom.cpp b/src/cc/CCcustom.cpp index 6c66b3599fd..ac13bd6d5a4 100644 --- a/src/cc/CCcustom.cpp +++ b/src/cc/CCcustom.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "key_io.h" #include "CCinclude.h" #include "CCassets.h" diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 1d28e2cc939..d92ab7d3d74 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -285,13 +285,6 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo /// @param[out] currentheight current chain height bool NSPV_myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, int32_t &txheight, int32_t ¤theight); -/// decodes char array in hex encoding to byte array -int32_t decode_hex(uint8_t *bytes, int32_t n, char *hex); - -/// checks if char string has hex symbols -/// @returns no zero if string has only hex symbols -int32_t is_hexstr(char *str,int32_t n); - /// CCgettxout returns the amount of an utxo. The function does this without loading the utxo transaction from the chain, by using coin cache /// @param txid transaction id of the utxo /// @param vout utxo transaction vout order number diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index 36495314887..f4a4db8444e 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -26,6 +26,7 @@ #include "chain.h" #include "core_io.h" #include "crosschain.h" +#include "hex.h" #define FAUCET2SIZE COIN #define EVAL_FAUCET2 EVAL_FIRSTUSER @@ -612,7 +613,7 @@ std::string CClib_rawtxgen(struct CCcontract_info *cp,uint8_t funcid,cJSON *para if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) { len >>= 1; - decode_hex(buf,len,(char *)rawhex.c_str()); + decode_hex(buf,len,rawhex.c_str()); hash = bits256_doublesha256(0,buf,len); if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) { diff --git a/src/cc/crypto777/OS_portable.h b/src/cc/crypto777/OS_portable.h index e0b185cbc72..5dd8f388f9f 100755 --- a/src/cc/crypto777/OS_portable.h +++ b/src/cc/crypto777/OS_portable.h @@ -288,7 +288,6 @@ int64_t iguana_memfree(struct OS_memspace *mem,void *ptr,int32_t size); // generic functions bits256 iguana_merkle(char *symbol,bits256 *tree,int32_t txn_count); bits256 bits256_calctxid(char *symbol,uint8_t *serialized,int32_t len); -int32_t unhex(char c); void touppercase(char *str); uint32_t is_ipaddr(char *str); void iguana_bitmap(char *space,int32_t max,char *name); @@ -298,13 +297,10 @@ uint64_t stringbits(char *str); int32_t is_decimalstr(char *str); void tolowercase(char *str); char *clonestr(char *str); -int32_t is_hexstr(char *str,int32_t n); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); void reverse_hexstr(char *str); int32_t init_hexbytes_noT(char *hexbytes,uint8_t *message,long len); uint16_t parse_ipaddr(char *ipaddr,char *ip_port); int32_t bitweight(uint64_t x); -uint8_t _decode_hex(char *hex); char *uppercase_str(char *buf,char *str); char *lowercase_str(char *buf,char *str); int32_t strsearch(char *strs[],int32_t num,char *name); diff --git a/src/cc/dapps/dappstd.c b/src/cc/dapps/dappstd.c index 82366315c95..bb612c22e4c 100644 --- a/src/cc/dapps/dappstd.c +++ b/src/cc/dapps/dappstd.c @@ -81,112 +81,6 @@ double OS_milliseconds() return(millis); } -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index ac1f8840095..1db07722697 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -31,108 +31,6 @@ void myprintf(const char* format, ...) va_end( marker ); } -char hexbyte(int32_t c) -{ - c &= 0xf; - if ( c < 10 ) - return('0'+c); - else if ( c < 16 ) - return('a'+c-10); - else return(0); -} - -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //myprintf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //myprintf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - myprintf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //myprintf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //myprintf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; diff --git a/src/cc/dapps/zmigrate.c b/src/cc/dapps/zmigrate.c index f7d9e3feb51..30d8fc5320a 100644 --- a/src/cc/dapps/zmigrate.c +++ b/src/cc/dapps/zmigrate.c @@ -35,108 +35,6 @@ bits256 zeroid; -char hexbyte(int32_t c) -{ - c &= 0xf; - if ( c < 10 ) - return('0'+c); - else if ( c < 16 ) - return('a'+c-10); - else return(0); -} - -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 48d1049f91f..dc57602cf74 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCdice.h" // timeout @@ -936,7 +936,7 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, if ( (iswin= DiceIsWinner(entropy,entropyvout,txid,tx,vinTx,hash,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 ) { // will only happen for fundingPubKey - if ( KOMODO_INSYNC != 0 && KOMODO_DEALERNODE != 0 ) + if ( KOMODO_INSYNC != 0 && IS_KOMODO_DEALERNODE != 0 ) DiceQueue(iswin,sbits,fundingtxid,txid,tx,entropyvout); } else @@ -1788,8 +1788,8 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx { if ( myGetTransaction(betTx.vin[0].prevout.hash,entropyTx,hashBlock) != 0 ) { - flag = KOMODO_DEALERNODE != 0; - if ( KOMODO_DEALERNODE != 0 && scriptPubKey == fundingPubKey ) + flag = IS_KOMODO_DEALERNODE != 0; + if ( IS_KOMODO_DEALERNODE != 0 && scriptPubKey == fundingPubKey ) { bettorentropy = DiceGetEntropy(betTx,'B'); if ( (iswin= DiceIsWinner(hentropyproof,entropyvout,txid,betTx,entropyTx,bettorentropy,sbits,minbet,maxbet,maxodds,timeoutblocks,fundingtxid)) != 0 ) @@ -1818,7 +1818,7 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx } } } - if ( didinit == 0 && KOMODO_DEALERNODE == 0 && scriptPubKey == fundingPubKey ) + if ( didinit == 0 && IS_KOMODO_DEALERNODE == 0 && scriptPubKey == fundingPubKey ) { strcpy(_planstr,planstr); dealer0_fundingtxid = fundingtxid; diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index 2c0a08451f1..74dfe43d966 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCfaucet.h" #include "../txmempool.h" @@ -202,7 +202,7 @@ UniValue FaucetGet(const CPubKey& pk, uint64_t txfee) if ( (len= (int32_t)result[JSON_HEXTX].getValStr().size()) > 0 && len < 65536 ) { len >>= 1; - decode_hex(buf,len,(char *)result[JSON_HEXTX].getValStr().c_str()); + decode_hex(buf,len,result[JSON_HEXTX].getValStr().c_str()); hash = bits256_doublesha256(0,buf,len); if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) { diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp index 68625c0382b..91c458eaec6 100644 --- a/src/cc/marmara.cpp +++ b/src/cc/marmara.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCMarmara.h" /* diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 0c6edb284dc..048ade82adb 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -12,7 +12,7 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ - +#include "hex.h" #include "CCPayments.h" /* diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 0fcc2e512c3..f0debddba90 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -1961,24 +1961,14 @@ UniValue PricesRekt(int64_t txfee, uint256 bettxid, int32_t rektheight) for (int i = 0; i<1000000; i++, nonce++) { CMutableTransaction tmpmtx = mtx; - //int32_t len; - //uint8_t txbuf[32768]; rawtx = FinalizeCCTx(0, cp, tmpmtx, mypk, txfee, prices_finalopret(true, bettxid, mypk, betinfo.lastheight, betinfo.averageCostbasis, betinfo.lastprice, betinfo.liquidationprice, betinfo.equity, myfee, nonce)); - //if ((len = (int32_t)rawtx.size()) > 0 && len < sizeof(txbuf) / sizeof(txbuf[0]) * 2) - //{ - // len >>= 1; // sizeof hex divide by 2 - //decode_hex(txbuf, len, (char *)rawtx.c_str()); - //bits256 hash = bits256_doublesha256(0, txbuf, len); - uint256 hash = tmpmtx.GetHash(); - //if ((hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0) - if ((hash.begin()[0] & 0xff) == 0 && (hash.begin()[31] & 0xff) == 0) - { - fprintf(stderr, "found valid txid after %d iterations %u\n", i, (uint32_t)time(NULL)); - return(prices_rawtxresult(result, rawtx, 0)); - } - //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); - //} + uint256 hash = tmpmtx.GetHash(); + if ((hash.begin()[0] & 0xff) == 0 && (hash.begin()[31] & 0xff) == 0) + { + fprintf(stderr, "found valid txid after %d iterations %u\n", i, (uint32_t)time(NULL)); + return(prices_rawtxresult(result, rawtx, 0)); + } } fprintf(stderr, "couldnt generate valid txid %u\n", (uint32_t)time(NULL)); diff --git a/src/cc/rogue/extern.h b/src/cc/rogue/extern.h index c62646b67ee..2c3905daae5 100644 --- a/src/cc/rogue/extern.h +++ b/src/cc/rogue/extern.h @@ -194,7 +194,5 @@ void md_onsignal_exit(void); void md_onsignal_default(void); int md_issymlink(char *sp); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); - #endif diff --git a/src/cc/rogue/main.c b/src/cc/rogue/main.c index 093b73d703d..29b0cf7305b 100644 --- a/src/cc/rogue/main.c +++ b/src/cc/rogue/main.c @@ -76,112 +76,6 @@ double OS_milliseconds() return(millis); } -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} - long _stripwhite(char *buf,int accept) { int32_t i,j,c; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 679a6913a42..95b86adfe3f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -571,7 +571,7 @@ void *chainparams_commandline() pCurrentParams->SetNValue(ASSETCHAINS_NK[0]); pCurrentParams->SetKValue(ASSETCHAINS_NK[1]); } - if ( KOMODO_TESTNODE != 0 ) + if ( IS_KOMODO_TESTNODE ) pCurrentParams->SetMiningRequiresPeers(false); if ( ASSETCHAINS_RPCPORT == 0 ) ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; diff --git a/src/hex.c b/src/hex.c new file mode 100644 index 00000000000..55d6a645337 --- /dev/null +++ b/src/hex.c @@ -0,0 +1,143 @@ +#include +#include "hex.h" + +/*** + * turn a char into its hex value + * A '5' becomes a 5, 'B' (or 'b') becomes 11. + * @param c the input + * @returns the value + */ +int32_t unhex(char c) +{ + if ( c >= '0' && c <= '9' ) + return(c - '0'); + else if ( c >= 'a' && c <= 'f' ) + return(c - 'a' + 10); + else if ( c >= 'A' && c <= 'F' ) + return(c - 'A' + 10); + return(-1); +} + +/*** + * Check n characters of a string to see if it can be + * interpreted as a hex string + * @param str the input + * @param n the size of input to check, 0 to check until null terminator found + * @returns 0 on error, othewise a positive number + */ +int32_t is_hexstr(const char *str,int32_t n) +{ + int32_t i; + if ( str == 0 || str[0] == 0 ) + return(0); + for (i=0; str[i]!=0; i++) + { + if ( n > 0 && i >= n ) + break; + if ( unhex(str[i]) < 0 ) + break; + } + if ( n == 0 ) + return(i); + return(i == n); +} + +/*** + * Decode a 2 character hex string into its value + * @param hex the string (i.e. 'ff') + * @returns the value (i.e. 255) + */ +unsigned char _decode_hex(const char *hex) +{ + return (unhex(hex[0])<<4) | unhex(hex[1]); +} + +/*** + * Turn a hex string into bytes + * @param bytes where to store the output + * @param n number of bytes to process + * @param hex the input (will ignore CR/LF) + * @returns the number of bytes processed (not an indicator of success) + */ +int32_t decode_hex(uint8_t *bytes, int32_t n,const char *str) +{ + int32_t adjust = 0; + + // check validity of input + if ( is_hexstr(str,n) <= 0 ) + { + memset(bytes,0,n); // give no results + return(n); + } + // ignore CR/LF + while(str[n-1] == '\n' || str[n-1] == '\r') + --n; + if ( n == 0 || (str[n*2+1] == 0 && str[n*2] != 0) ) + { + if ( n > 0 ) + { + bytes[0] = unhex(str[0]); + } + bytes++; + str++; + adjust = 1; + } + if ( n > 0 ) + { + for (int i=0; i>4) & 0xf); + hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); + } + hexbytes[len*2] = 0; + return((int32_t)len*2+1); +} + +/*** + * Convert a bits256 into a hex character string + * @param hexstr the results + * @param x the input + * @returns a pointer to hexstr + */ +char *bits256_str(char hexstr[65],bits256 x) +{ + init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); + return(hexstr); +} diff --git a/src/hex.h b/src/hex.h new file mode 100644 index 00000000000..ccc4ccde87c --- /dev/null +++ b/src/hex.h @@ -0,0 +1,70 @@ +/*** + * Routines for char to hex conversions + */ +#pragma once +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef _BITS256 +#define _BITS256 + union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; + typedef union _bits256 bits256; +#endif + +/*** + * turn a char into its hex value + * A '5' becomes a 5, 'B' (or 'b') becomes 11. + * @param c the input + * @returns the value + */ +int32_t unhex(char c); + +/*** + * Check n characters of a string to see if it can be + * interpreted as a hex string + * @param str the input + * @param n the size of input to check, 0 to check until null terminator found + * @returns 0 on error, othewise a positive number + */ +int32_t is_hexstr(const char *str,int32_t n); + +/*** + * Decode a 2 character hex string into its value + * @param hex the string (i.e. 'ff') + * @returns the value (i.e. 255) + */ +unsigned char _decode_hex(const char *hex) ; + +/*** + * Turn a hex string into bytes + * @param bytes where to store the output + * @param n number of bytes to process + * @param hex the input (will ignore CR/LF) + * @returns the number of bytes processed (not an indicator of success) + */ +int32_t decode_hex(uint8_t *bytes, int32_t n,const char *in); + +/**** + * Convert a binary array of bytes into a hex string + * @param hexbytes the result + * @param message the array of bytes + * @param len the length of message + * @returns the length of hexbytes (including null terminator) + */ +int32_t init_hexbytes_noT(char *hexbytes, unsigned char *message, long len); + +/*** + * Convert a bits256 into a hex character string + * @param hexstr the results + * @param x the input + * @returns a pointer to hexstr + */ +char *bits256_str(char hexstr[65], bits256 x); + +#ifdef __cplusplus +} +#endif diff --git a/src/komodo.h b/src/komodo.h index 88e741df7f7..f37c9c28cb1 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -547,13 +547,13 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar return(-1); if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac ) { - if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY != 0 ) + if ( i == 0 && j == 0 && memcmp(NOTARY_PUBKEY33,scriptbuf+1,33) == 0 && IS_KOMODO_NOTARY ) { printf("%s KOMODO_LASTMINED.%d -> %d\n",ASSETCHAINS_SYMBOL,KOMODO_LASTMINED,height); prevKOMODO_LASTMINED = KOMODO_LASTMINED; KOMODO_LASTMINED = height; } - decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); + decode_hex(crypto777,33,CRYPTO777_PUBSECPSTR); /*for (k=0; k<33; k++) printf("%02x",crypto777[k]); printf(" crypto777 "); @@ -835,7 +835,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) } //fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); // Wallet Filter. Disabled here. Cant be activated by notaries or pools with some changes. - if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || IS_STAKED_NOTARY > -1 ) + if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || STAKED_NOTARY_ID > -1 ) { staked_era = STAKED_era(pindex->GetBlockTime()); if ( !fJustCheck && staked_era != lastStakedEra ) @@ -937,26 +937,8 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) sp->NOTARIZED_HASH = block.GetHash(); sp->NOTARIZED_DESTTXID = txhash; } - //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - // printf("(tx.%d: ",i); for (j=0; j= 235300 && block.vtx[0].vout[1].nValue >= 100000*COIN ) - block.vtx[0].vout[1].nValue = 0; - break; - } - } - }*/ - //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - // printf("%.8f ",dstr(block.vtx[i].vout[j].nValue)); len = block.vtx[i].vout[j].scriptPubKey.size(); if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) ) @@ -976,8 +958,6 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) } } } - //if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) - // printf(") "); if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 ) printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d notarized.%d special.%d isratification.%d\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts,notarized,specialtx,isratification); if ( !fJustCheck && (notarized != 0 && (notarizedheight != 0 || specialtx != 0)) ) @@ -1018,7 +998,7 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) } } } - if ( !fJustCheck && IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( !fJustCheck && IS_KOMODO_NOTARY && ASSETCHAINS_SYMBOL[0] == 0 ) printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height); if ( !fJustCheck && pindex->GetHeight() == hwmheight ) komodo_stateupdate(height,0,0,0,zero,0,0,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0); diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 137e0b16b3d..e8a8b5572a2 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -574,34 +574,6 @@ CScript komodo_makeopret(CBlock *pblock, bool fNew) return(opret); } -/*uint256 komodo_getblockhash(int32_t height) - { - uint256 hash; char params[128],*hexstr,*jsonstr; cJSON *result; int32_t i; uint8_t revbuf[32]; - memset(&hash,0,sizeof(hash)); - sprintf(params,"[%d]",height); - if ( (jsonstr= komodo_issuemethod(KMDUSERPASS,(char *)"getblockhash",params,BITCOIND_RPCPORT)) != 0 ) - { - if ( (result= cJSON_Parse(jsonstr)) != 0 ) - { - if ( (hexstr= jstr(result,(char *)"result")) != 0 ) - { - if ( is_hexstr(hexstr,0) == 64 ) - { - decode_hex(revbuf,32,hexstr); - for (i=0; i<32; i++) - ((uint8_t *)&hash)[i] = revbuf[31-i]; - } - } - free_json(result); - } - printf("KMD hash.%d (%s) %x\n",height,jsonstr,*(uint32_t *)&hash); - free(jsonstr); - } - return(hash); - } - - uint256 _komodo_getblockhash(int32_t height);*/ - uint64_t komodo_seed(int32_t height) { uint64_t seed = 0; @@ -827,7 +799,7 @@ int32_t komodo_is_notarytx(const CTransaction& tx) if ( ptr != 0 ) { if ( crypto777[0] == 0 ) - decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR); + decode_hex(crypto777,33,CRYPTO777_PUBSECPSTR); if ( memcmp(ptr+1,crypto777,33) == 0 ) { //printf("found notarytx\n"); @@ -2282,7 +2254,7 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height) } if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) ) { - decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + decode_hex(scripthex,scriptlen,ASSETCHAINS_SCRIPTPUB.c_str()); if ( memcmp(scripthex,script,scriptlen) == 0 ) matched = scriptlen; } @@ -2471,7 +2443,7 @@ int32_t komodo_checkPOW(int64_t stakeTxValue, int32_t slowflag,CBlock *pblock,in 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()); + decode_hex(scripthex,scriptlen,ASSETCHAINS_SCRIPTPUB.c_str()); if ( memcmp(scripthex,script,scriptlen) != 0 ) return(-1); } else return(-1); @@ -2794,7 +2766,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt earliest = eligible; best_scriptPubKey = kp->scriptPubKey; *utxovaluep = (uint64_t)kp->nValue; - decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str()); + decode_hex((uint8_t *)utxotxidp,32,kp->txid.GetHex().c_str()); *utxovoutp = kp->vout; *txtimep = kp->txtime; } diff --git a/src/komodo_cJSON.c b/src/komodo_cJSON.c index 10140ad0232..b5f6c24244a 100644 --- a/src/komodo_cJSON.c +++ b/src/komodo_cJSON.c @@ -28,6 +28,7 @@ #include "cJSON.h" #include "komodo_cJSON.h" #include "cJSON.c" +#include "hex.h" #ifndef DBL_EPSILON #define DBL_EPSILON 2.2204460492503131E-16 diff --git a/src/komodo_defs.h b/src/komodo_defs.h index b4b118a5760..51f1e717bae 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -491,7 +491,8 @@ extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_FOUNDERS_REWARD; extern uint64_t ASSETCHAINS_TIMELOCKGTE; extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH,ASSETCHAINS_EQUIHASH,KOMODO_INITDONE; -extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE,ASSETCHAINS_STAKED,KOMODO_NSPV; +extern bool IS_KOMODO_NOTARY; +extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE,ASSETCHAINS_STAKED,KOMODO_NSPV; extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA,ASSETCHAINS_CBOPRET; extern bool VERUS_MINTBLOCKS; extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS+1], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[],ASSETCHAINS_NK[2]; @@ -505,21 +506,23 @@ extern std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; extern uint256 KOMODO_EARLYTXID; -extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE,KOMODO_DEALERNODE; +extern bool IS_KOMODO_DEALERNODE; +extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE; extern uint32_t ASSETCHAINS_CC; extern std::string CCerror,ASSETCHAINS_CCLIB; extern uint8_t ASSETCHAINS_CCDISABLES[256]; extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; -extern int32_t KOMODO_EXCHANGEWALLET; +extern bool IS_MODE_EXCHANGEWALLET; extern int32_t VERUS_MIN_STAKEAGE; extern std::string DONATION_PUBKEY; extern uint8_t ASSETCHAINS_PRIVATE; extern int32_t USE_EXTERNAL_PUBKEY; extern char NOTARYADDRS[64][64]; extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; -extern int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL,IS_STAKED_NOTARY,STAKED_ERA; +extern bool IS_KOMODO_TESTNODE; +extern int32_t KOMODO_SNAPSHOT_INTERVAL,STAKED_NOTARY_ID,STAKED_ERA; extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT; extern int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; int tx_height( const uint256 &hash ); diff --git a/src/komodo_events.h b/src/komodo_events.h index 5500a341eb2..a597affeb39 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -41,14 +41,14 @@ void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t heig { static uint32_t counter; int32_t verified=0; char *coin; struct komodo_event_notarized N; coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; - if ( IS_KOMODO_NOTARY != 0 && (verified= komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid)) < 0 ) + if ( IS_KOMODO_NOTARY && (verified= komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid)) < 0 ) { if ( counter++ < 100 ) printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n",ASSETCHAINS_SYMBOL,height,notarizedheight,dest); } else if ( strcmp(symbol,coin) == 0 ) { - if ( 0 && IS_KOMODO_NOTARY != 0 && verified != 0 ) + if ( 0 && IS_KOMODO_NOTARY && verified != 0 ) fprintf(stderr,"validated [%s] ht.%d notarized %d\n",coin,height,notarizedheight); memset(&N,0,sizeof(N)); N.blockhash = notarized_hash; diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 063364230e5..c85b4acd1d6 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -55,7 +55,10 @@ int COINBASE_MATURITY = _COINBASE_MATURITY;//100; unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; uint256 KOMODO_EARLYTXID; -int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,IS_STAKED_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS,ASSETCHAINS_CBMATURITY,KOMODO_NSPV; +bool IS_KOMODO_NOTARY; +bool IS_MODE_EXCHANGEWALLET; +bool IS_KOMODO_DEALERNODE; +int32_t KOMODO_MININGTHREADS = -1,STAKED_NOTARY_ID,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS,ASSETCHAINS_CBMATURITY,KOMODO_NSPV; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB; uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA; @@ -118,10 +121,11 @@ uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REW uint32_t KOMODO_INITDONE; char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; uint64_t PENDING_KOMODO_TX; -extern int32_t KOMODO_LOADINGBLOCKS; +extern int32_t KOMODO_LOADINGBLOCKS; // defined in pow.cpp, boolean, 1 if currently loading the block index, 0 if not unsigned int MAX_BLOCK_SIGOPS = 20000; -int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL; +bool IS_KOMODO_TESTNODE; +int32_t KOMODO_SNAPSHOT_INTERVAL; CScript KOMODO_EARLYTXID_SCRIPTPUB; int32_t ASSETCHAINS_EARLYTXIDCONTRACT; int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; diff --git a/src/komodo_kv.h b/src/komodo_kv.h index a879340ffea..048794a89ef 100644 --- a/src/komodo_kv.h +++ b/src/komodo_kv.h @@ -17,6 +17,7 @@ #define H_KOMODOKV_H #include "komodo_defs.h" +#include "hex.h" int32_t komodo_kvcmp(uint8_t *refvalue,uint16_t refvaluesize,uint8_t *value,uint16_t valuesize) { diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index b17c7b104da..ea6156a5b2c 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -729,7 +729,7 @@ uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint2 if ( *txlenp > 0 ) { rawtx = (uint8_t *)calloc(1,*txlenp); - decode_hex(rawtx,*txlenp,(char *)strHex.c_str()); + decode_hex(rawtx,*txlenp,strHex.c_str()); } } return(rawtx); diff --git a/src/komodo_notary.h b/src/komodo_notary.h index f820e0bd568..69631987f8a 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -491,7 +491,7 @@ void komodo_init(int32_t height) if ( didinit == 0 ) { pthread_mutex_init(&komodo_mutex,NULL); - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + decode_hex(NOTARY_PUBKEY33,33,NOTARY_PUBKEY.c_str()); if ( height >= 0 ) { n = (int32_t)(sizeof(Notaries_genesis)/sizeof(*Notaries_genesis)); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index f21241cccc2..df559e15966 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -13,6 +13,7 @@ * * ******************************************************************************/ #include "komodo_defs.h" +#include "hex.h" #include "key_io.h" #include "cc/CCinclude.h" #include @@ -822,112 +823,6 @@ int32_t bitweight(uint64_t x) return(wt); } -int32_t _unhex(char c) -{ - if ( c >= '0' && c <= '9' ) - return(c - '0'); - else if ( c >= 'a' && c <= 'f' ) - return(c - 'a' + 10); - else if ( c >= 'A' && c <= 'F' ) - return(c - 'A' + 10); - return(-1); -} - -int32_t is_hexstr(char *str,int32_t n) -{ - int32_t i; - if ( str == 0 || str[0] == 0 ) - return(0); - for (i=0; str[i]!=0; i++) - { - if ( n > 0 && i >= n ) - break; - if ( _unhex(str[i]) < 0 ) - break; - } - if ( n == 0 ) - return(i); - return(i == n); -} - -int32_t unhex(char c) -{ - int32_t hex; - if ( (hex= _unhex(c)) < 0 ) - { - //printf("unhex: illegal hexchar.(%c)\n",c); - } - return(hex); -} - -unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } - -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) -{ - int32_t adjust,i = 0; - //printf("decode.(%s)\n",hex); - if ( is_hexstr(hex,n) <= 0 ) - { - memset(bytes,0,n); - return(n); - } - if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) - hex[--n] = 0; - if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) - { - if ( n > 0 ) - { - bytes[0] = unhex(hex[0]); - printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); - } - bytes++; - hex++; - adjust = 1; - } else adjust = 0; - if ( n > 0 ) - { - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} - int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) { int32_t i; uint64_t x; @@ -1695,37 +1590,44 @@ int8_t equihash_params_possible(uint64_t n, uint64_t k) return(-1); } +/*** + * Parse command line arguments + * @param argv0 the arguments + */ void komodo_args(char *argv0) { - std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; - FILE *fp; uint64_t val; uint16_t port, dest_rpc_port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; + uint8_t extrabuf[32756], *extraptr = 0; + int32_t i; + int32_t n; + int32_t nonz=0; + int32_t extralen = 0; + uint64_t ccEnablesHeight[512] = {0}; std::string ntz_dest_path; ntz_dest_path = GetArg("-notary", ""); - IS_KOMODO_NOTARY = ntz_dest_path == "" ? 0 : 1; + IS_KOMODO_NOTARY = !ntz_dest_path.empty(); - - IS_STAKED_NOTARY = GetArg("-stakednotary", -1); + STAKED_NOTARY_ID = GetArg("-stakednotary", -1); KOMODO_NSPV = GetArg("-nSPV",0); - memset(ccenables,0,sizeof(ccenables)); + uint8_t disablebits[32]; memset(disablebits,0,sizeof(disablebits)); memset(ccEnablesHeight,0,sizeof(ccEnablesHeight)); if ( GetBoolArg("-gen", false) != 0 ) { KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); } - if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 ) - fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n"); + if ( (IS_MODE_EXCHANGEWALLET = GetBoolArg("-exchange", false)) ) + fprintf(stderr,"IS_MODE_EXCHANGEWALLET mode active\n"); DONATION_PUBKEY = GetArg("-donation", ""); NOTARY_PUBKEY = GetArg("-pubkey", ""); - KOMODO_DEALERNODE = GetArg("-dealer",0); - KOMODO_TESTNODE = GetArg("-testnode",0); + IS_KOMODO_DEALERNODE = GetBoolArg("-dealer",false); + IS_KOMODO_TESTNODE = GetArg("-testnode",0); ASSETCHAINS_STAKED_SPLIT_PERCENTAGE = GetArg("-splitperc",0); - if ( strlen(NOTARY_PUBKEY.c_str()) == 66 ) + if ( NOTARY_PUBKEY.size() == 66 ) { - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + decode_hex(NOTARY_PUBKEY33,33,NOTARY_PUBKEY.c_str()); USE_EXTERNAL_PUBKEY = 1; - if ( IS_KOMODO_NOTARY == 0 ) + if ( !IS_KOMODO_NOTARY ) { // We dont have any chain data yet, so use system clock to guess. // I think on season change should reccomend notaries to use -notary to avoid needing this. @@ -1734,24 +1636,24 @@ void komodo_args(char *argv0) { if ( strcmp(NOTARY_PUBKEY.c_str(),notaries_elected[kmd_season-1][i][1]) == 0 ) { - IS_KOMODO_NOTARY = 1; + IS_KOMODO_NOTARY = true; KOMODO_MININGTHREADS = 1; mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS); - IS_STAKED_NOTARY = -1; + STAKED_NOTARY_ID = -1; fprintf(stderr,"running as notary.%d %s\n",i,notaries_elected[kmd_season-1][i][0]); break; } } } } - if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) { + if ( STAKED_NOTARY_ID != -1 && IS_KOMODO_NOTARY ) { fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n"); StartShutdown(); } - name = GetArg("-ac_name",""); + std::string name = GetArg("-ac_name",""); if ( argv0 != 0 ) { - len = (int32_t)strlen(argv0); + size_t len = strlen(argv0); for (i=0; i 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 ) - { - fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); + if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 + || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 + || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 + || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 + || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF + || ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 + || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 + || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 + || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 + || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 + || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 ) + { + fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100, + ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2], + (int32_t)ASSETCHAINS_SCRIPTPUB.size()); extraptr = extrabuf; memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; @@ -2125,7 +2041,7 @@ void komodo_args(char *argv0) extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS); } - val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; + uint64_t val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); if ( ASSETCHAINS_FOUNDERS != 0 ) @@ -2142,7 +2058,7 @@ void komodo_args(char *argv0) } if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) { - decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,ASSETCHAINS_SCRIPTPUB.c_str()); extralen += ASSETCHAINS_SCRIPTPUB.size()/2; //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); @@ -2161,7 +2077,7 @@ void komodo_args(char *argv0) extraptr[extralen++] = 'c'; if ( ASSETCHAINS_MARMARA != 0 ) extraptr[extralen++] = ASSETCHAINS_MARMARA; -fprintf(stderr,"extralen.%d before disable bits\n",extralen); + fprintf(stderr,"extralen.%d before disable bits\n",extralen); if ( nonz > 0 ) { memcpy(&extraptr[extralen],disablebits,sizeof(disablebits)); @@ -2190,7 +2106,7 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); { for (i=0; i 0 ) + std::string addn = GetArg("-seednode",""); + if ( !addn.empty() ) ASSETCHAINS_SEED = 1; strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); MAX_MONEY = komodo_max_money(); + int32_t baseid; if ( (baseid = komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) { - //komodo_maxallowed(baseid); printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); } @@ -2248,7 +2164,6 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); if ( KOMODO_BIT63SET(MAX_MONEY) != 0 ) MAX_MONEY = KOMODO_MAXNVALUE; fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); - //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); if ( GetArg("-port",0) != 0 ) { @@ -2256,7 +2171,8 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); fprintf(stderr,"set p2pport.%u\n",ASSETCHAINS_P2PPORT); } else ASSETCHAINS_P2PPORT = tmpport; - while ( (dirname= (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) + char *dirname; + while ( (dirname = (char *)GetDataDir(false).string().c_str()) == 0 || dirname[0] == 0 ) { fprintf(stderr,"waiting for datadir (%s)\n",dirname); #ifndef _WIN32 @@ -2265,7 +2181,6 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); boost::this_thread::sleep(boost::posix_time::milliseconds(3000)); #endif } - //fprintf(stderr,"Got datadir.(%s)\n",dirname); if ( ASSETCHAINS_SYMBOL[0] != 0 ) { int32_t komodo_baseid(char *origbase); @@ -2275,6 +2190,7 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); fprintf(stderr,"cant have assetchain named KMD\n"); StartShutdown(); } + uint16_t port; if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) ASSETCHAINS_RPCPORT = port; else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); @@ -2292,23 +2208,23 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); } if ( ASSETCHAINS_RPCPORT == 0 ) ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; - //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); - //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); + uint8_t magic[4]; iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); - for (i=0; i<4; i++) - sprintf(&magicstr[i<<1],"%02x",magic[i]); - magicstr[8] = 0; #ifndef FROM_CLI - sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); - if ( (fp= fopen(fname,"wb")) != 0 ) - { + std::string fname = std::string(ASSETCHAINS_SYMBOL) + "_7776"; + FILE* fp; + if ( (fp= fopen(fname.c_str(),"wb")) != 0 ) + { + char magicstr[9]; + for (i=0; i<4; i++) + sprintf(&magicstr[i<<1],"%02x",magic[i]); + magicstr[8] = 0; int8_t notarypay = 0; if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) notarypay = 1; fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146",notarypay); fclose(fp); - //printf("created (%s)\n",fname); - } else printf("error creating (%s)\n",fname); + } else printf("error creating (%s)\n",fname.c_str()); #endif if ( ASSETCHAINS_CC < 2 ) { @@ -2326,7 +2242,9 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); } else { - char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; + char fname[512],username[512],password[4096]; + int32_t iter; + FILE *fp; ASSETCHAINS_P2PPORT = 7770; ASSETCHAINS_RPCPORT = 7771; for (iter=0; iter<2; iter++) @@ -2353,12 +2271,12 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); #endif if ( (fp= fopen(fname,"rb")) != 0 ) { - dest_rpc_port = _komodo_userpass(username,password,fp); + uint16_t dest_rpc_port = _komodo_userpass(username,password,fp); DEST_PORT = iter == 1 ? dest_rpc_port : 0; sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); fclose(fp); } else printf("couldnt open.(%s) will not validate dest notarizations\n",fname); - if ( IS_KOMODO_NOTARY == 0 ) + if ( !IS_KOMODO_NOTARY ) break; } } @@ -2366,7 +2284,6 @@ fprintf(stderr,"extralen.%d before disable bits\n",extralen); if ( ASSETCHAINS_SYMBOL[0] != 0 ) { BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); - //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) { ASSETCHAINS_HALVING[0] *= 5; diff --git a/src/main.cpp b/src/main.cpp index 7d0d52424ed..b61d7bb79c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3803,7 +3803,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0].GetValueOut(), blockReward), REJECT_INVALID, "bad-cb-amount"); - } else if ( IS_KOMODO_NOTARY != 0 ) + } else if ( IS_KOMODO_NOTARY ) fprintf(stderr,"allow nHeight.%d coinbase %.8f vs %.8f interest %.8f\n",(int32_t)pindex->GetHeight(),dstr(block.vtx[0].GetValueOut()),dstr(blockReward),dstr(sum)); } if (!control.Wait()) @@ -6014,6 +6014,13 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) return true; } +/**** + * Open a file + * @param pos where to position for the next read + * @param prefix the type of file (i.e. "blk", "rev", etc. + * @param fReadOnly open in read only mode + * @returns the file pointer or NULL on error + */ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { static int32_t didinit[256]; @@ -6021,9 +6028,9 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) return NULL; boost::filesystem::path path = GetBlockPosFilename(pos, prefix); boost::filesystem::create_directories(path.parent_path()); - FILE* file = fopen(path.string().c_str(), "rb+"); + FILE* file = fopen(path.string().c_str(), "rb+"); // open existing file for reading and writing if (!file && !fReadOnly) - file = fopen(path.string().c_str(), "wb+"); + file = fopen(path.string().c_str(), "wb+"); // create an empty file for reading and writing if (!file) { LogPrintf("Unable to open file %s\n", path.string()); return NULL; @@ -6043,14 +6050,32 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) return file; } +/*** + * Open a block file + * @param pos where to position for the next read + * @param fReadOnly true to open the file in read only mode + * @returns the file pointer or NULL on error + */ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "blk", fReadOnly); } +/*** + * Open an undo ("rev") file + * @param pos where to position for the next read + * @param fReadOnly true to open the file in read only mode + * @returns the file pointer or NULL on error + */ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "rev", fReadOnly); } +/*** + * Get the full filename (including path) or a specific .dat file + * @param pos the block position + * @param prefix the prefix (i.e. "blk" or "rev") + * @returns the filename with the complete path + */ boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) { return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile); @@ -6543,6 +6568,10 @@ void UnloadBlockIndex() fHavePruned = false; } +/*** + * Load block index + * @returns true on success + */ bool LoadBlockIndex() { // Load block index from databases @@ -7728,12 +7757,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } pfrom->PushMessage("headers", vHeaders); } - /*else if ( IS_KOMODO_NOTARY != 0 ) - { - static uint32_t counter; - if ( counter++ < 3 ) - fprintf(stderr,"you can ignore redundant getheaders from peer.%d %d prev.%d\n",(int32_t)pfrom->id,(int32_t)(pindex ? pindex->GetHeight() : -1),pfrom->lasthdrsreq); - }*/ } diff --git a/src/miner.cpp b/src/miner.cpp index 95f1f166fe3..c8bd108f63e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -46,6 +46,8 @@ #include "ui_interface.h" #include "util.h" #include "utilmoneystr.h" +#include "hex.h" + #ifdef ENABLE_WALLET #include "wallet/wallet.h" #endif @@ -153,7 +155,6 @@ int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHeight, bool fNew, CScript scriptPubKey); int32_t komodo_newStakerActive(int32_t height, uint32_t timestamp); int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void* ptr); -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); int32_t komodo_is_notarytx(const CTransaction& tx); CScript Marmara_scriptPubKey(int32_t height,CPubKey pk); CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk); @@ -724,7 +725,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetTime()); else txNew.nLockTime = std::max((int64_t)(pindexPrev->nTime+1), GetTime()); - if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY && My_notaryid >= 0 ) txNew.vout[0].nValue += 5000; pblock->vtx[0] = txNew; @@ -756,7 +757,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 len >>= 1; txNew.vout[1].scriptPubKey.resize(len); ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0]; - decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + decode_hex(ptr,len,ASSETCHAINS_SCRIPTPUB.c_str()); } else { @@ -857,7 +858,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); - if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY && My_notaryid >= 0 ) { uint32_t r; CScript opret; void **ptr=0; CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); @@ -904,7 +905,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } if ( ptr!=0 ) free(ptr); } - else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) ) + else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || !IS_KOMODO_NOTARY || My_notaryid < 0) ) { CValidationState state; //fprintf(stderr,"check validity\n"); @@ -1021,7 +1022,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, len >>= 1; scriptPubKey.resize(len); ptr = (uint8_t *)&scriptPubKey[0]; - decode_hex(ptr,len,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); + decode_hex(ptr,len,ASSETCHAINS_SCRIPTPUB.c_str()); } } else if ( USE_EXTERNAL_PUBKEY != 0 ) @@ -1126,7 +1127,7 @@ static bool ProcessBlockFound(CBlock* pblock) #ifdef ENABLE_WALLET // Remove key from key pool - if ( IS_KOMODO_NOTARY == 0 ) + if ( !IS_KOMODO_NOTARY ) { if (GetArg("-mineraddress", "").empty()) { // Remove key from key pool @@ -1871,7 +1872,7 @@ void static BitcoinMiner() if ( i == 33 ) externalflag = 1; else externalflag = 0; - if ( IS_KOMODO_NOTARY != 0 ) + if ( IS_KOMODO_NOTARY ) { for (i=1; i<66; i++) if ( memcmp(pubkeys[i],pubkeys[0],33) == 0 ) @@ -1980,7 +1981,7 @@ void static BitcoinMiner() // MilliSleep(30); return false; } - if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetTime() ) + if ( IS_KOMODO_NOTARY && B.nTime > GetTime() ) { //fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime())); while ( GetTime() < B.nTime-2 ) @@ -1995,7 +1996,7 @@ void static BitcoinMiner() } if ( ASSETCHAINS_STAKED == 0 ) { - if ( IS_KOMODO_NOTARY != 0 ) + if ( IS_KOMODO_NOTARY ) { int32_t r; if ( (r= ((Mining_height + NOTARY_PUBKEY33[16]) % 64) / 8) > 0 ) diff --git a/src/net.cpp b/src/net.cpp index 5fe1660254f..111e7acdf90 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -467,13 +467,8 @@ void CNode::PushVersion() LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id); PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, strSubVersion, nBestHeight, true); -//fprintf(stderr,"KOMODO_NSPV.%d PUSH services.%llx\n",KOMODO_NSPV,(long long)nLocalServices); } - - - - std::map CNode::setBanned; CCriticalSection CNode::cs_setBanned; diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index db1696ed5ec..14b86cbc8a9 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -3,6 +3,7 @@ #include "crosschain.h" #include "cc/CCinclude.h" #include "komodo_defs.h" +#include "hex.h" #include extern pthread_mutex_t staked_mutex; @@ -81,7 +82,7 @@ int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era) { if ( didinit[era-1] == 0 ) { for (i=0; i #include "komodo_defs.h" +#include "hex.h" #include using namespace std; @@ -5489,7 +5490,6 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& m #include "script/sign.h" -int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); extern std::string NOTARY_PUBKEY; int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void *pTr) @@ -5538,7 +5538,6 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33, void * continue; } utxovalue = (uint64_t)nValue; - //decode_hex((uint8_t *)&utxotxid,32,(char *)out.tx->GetHash().GetHex().c_str()); utxotxid = out.tx->GetHash(); utxovout = out.i; best_scriptPubKey = out.tx->vout[out.i].scriptPubKey; @@ -5729,7 +5728,7 @@ UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (strlen(params[0].get_str().c_str()) == 66) { - decode_hex(pubkey33,33,(char *)params[0].get_str().c_str()); + decode_hex(pubkey33,33,params[0].get_str().c_str()); pubkey2addr((char *)Raddress,(uint8_t *)pubkey33); CBitcoinAddress address(Raddress); bool isValid = address.IsValid(); @@ -5743,14 +5742,14 @@ UniValue setpubkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { result.push_back(Pair("ismine", "true")); std::string notaryname; - if ( (IS_STAKED_NOTARY= StakedNotaryID(notaryname, Raddress)) > -1 ) + if ( (STAKED_NOTARY_ID= StakedNotaryID(notaryname, Raddress)) > -1 ) { result.push_back(Pair("IsNotary", notaryname)); - IS_KOMODO_NOTARY = 0; + IS_KOMODO_NOTARY = false; } } NOTARY_PUBKEY = params[0].get_str(); - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + decode_hex(NOTARY_PUBKEY33,33,NOTARY_PUBKEY.c_str()); USE_EXTERNAL_PUBKEY = 1; NOTARY_ADDRESS = address.ToString(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index db66de052c4..b37669b5dbb 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3423,7 +3423,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const !IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) { - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) { uint32_t locktime; int32_t txheight; CBlockIndex *tipindex; if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != 0 && chainActive.LastTip()->GetHeight() >= 60000 ) @@ -3550,30 +3550,20 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(coin.second); nValueRet += coin.first; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += pcoin->vout[i].interest; return true; } else if (n < nTargetValue + CENT) { vValue.push_back(coin); nTotalLower += n; - //if ( KOMODO_EXCHANGEWALLET == 0 && count < sizeof(interests)/sizeof(*interests) ) - //{ - //fprintf(stderr,"count.%d %.8f\n",count,(double)pcoin->vout[i].interest/COIN); - //interests[count++] = pcoin->vout[i].interest; - //} if ( nTotalLower > 4*nTargetValue + CENT ) { - //fprintf(stderr,"why bother with all the utxo if we have double what is needed?\n"); break; } } else if (n < coinLowestLarger.first) { coinLowestLarger = coin; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // lowest_interest = pcoin->vout[i].interest; } } @@ -3583,8 +3573,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(vValue[i].second); nValueRet += vValue[i].first; - //if ( KOMODO_EXCHANGEWALLET == 0 && i < count ) - // *interestp += interests[i]; } return true; } @@ -3595,8 +3583,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return false; setCoinsRet.insert(coinLowestLarger.second); nValueRet += coinLowestLarger.first; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += lowest_interest; return true; } @@ -3616,8 +3602,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(coinLowestLarger.second); nValueRet += coinLowestLarger.first; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += lowest_interest; } else { for (unsigned int i = 0; i < vValue.size(); i++) @@ -3625,8 +3609,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int { setCoinsRet.insert(vValue[i].second); nValueRet += vValue[i].first; - //if ( KOMODO_EXCHANGEWALLET == 0 && i < count ) - // *interestp += interests[i]; } LogPrint("selectcoins", "SelectCoins() best subset: "); @@ -3643,11 +3625,6 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set vCoinsNoCoinbase, vCoinsWithCoinbase; AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false); AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true); @@ -3665,7 +3642,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout[out.i].nValue; - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) value += out.tx->vout[out.i].interest; } if (value <= nTargetValue) { @@ -3675,7 +3652,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout[out.i].nValue; - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) valueWithCoinbase += out.tx->vout[out.i].interest; } fNeedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue); @@ -3689,8 +3666,6 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout[out.i].nValue; - //if ( KOMODO_EXCHANGEWALLET == 0 ) - // *interestp += out.tx->vout[out.i].interest; setCoinsRet.insert(make_pair(out.tx, out.i)); } return (nValueRet >= nTargetValue); @@ -3712,7 +3687,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout.size() <= outpoint.n) return false; nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue; - if ( KOMODO_EXCHANGEWALLET == 0 ) + if ( !IS_MODE_EXCHANGEWALLET ) nValueFromPresetInputs += pcoin->vout[outpoint.n].interest; setPresetCoins.insert(make_pair(pcoin, outpoint.n)); } else @@ -3929,7 +3904,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt //a chance at a free transaction. //But mempool inputs might still be in the mempool, so their age stays 0 //fprintf(stderr,"nCredit %.8f interest %.8f\n",(double)nCredit/COIN,(double)pcoin.first->vout[pcoin.second].interest/COIN); - if ( KOMODO_EXCHANGEWALLET == 0 && ASSETCHAINS_SYMBOL[0] == 0 ) + if ( !IS_MODE_EXCHANGEWALLET && ASSETCHAINS_SYMBOL[0] == 0 ) { interest2 += pcoin.first->vout[pcoin.second].interest; //fprintf(stderr,"%.8f ",(double)pcoin.first->vout[pcoin.second].interest/COIN); @@ -3939,11 +3914,6 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt age += 1; dPriority += (double)nCredit * age; } - //if ( KOMODO_EXCHANGEWALLET != 0 ) - //{ - //fprintf(stderr,"KOMODO_EXCHANGEWALLET disable interest sum %.8f, interest2 %.8f\n",(double)interest/COIN,(double)interest2/COIN); - //interest = 0; // interest2 also - //} if ( ASSETCHAINS_SYMBOL[0] == 0 && DONATION_PUBKEY.size() == 66 && interest2 > 5000 ) { CScript scriptDonation = CScript() << ParseHex(DONATION_PUBKEY) << OP_CHECKSIG; From 9385134631280f8307b58880afddf9bcadf9f4a7 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 11 Jun 2021 10:54:59 -0500 Subject: [PATCH 13/58] move bits256 to 1 header --- src/bits256.h | 14 ++++++++++++++ src/cc/CCinclude.h | 7 ------- src/cc/dapps/dappstd.c | 7 +------ src/cc/includes/curve25519.h | 12 +----------- src/cc/rogue/main.c | 8 ++------ src/cc/rogue/rogue.h | 7 +------ src/hex.h | 7 +------ src/komodo_cJSON.h | 7 +------ src/komodo_curve25519.h | 2 ++ src/komodo_port.c | 3 +-- src/komodo_structs.h | 9 +-------- 11 files changed, 25 insertions(+), 58 deletions(-) create mode 100644 src/bits256.h diff --git a/src/bits256.h b/src/bits256.h new file mode 100644 index 00000000000..33c54ad558c --- /dev/null +++ b/src/bits256.h @@ -0,0 +1,14 @@ +#pragma once +#include "stdint.h" + +union _bits128 { uint8_t bytes[16]; uint16_t ushorts[8]; uint32_t uints[4]; uint64_t ulongs[2]; uint64_t txid; }; +typedef union _bits128 bits128; + +union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; +typedef union _bits256 bits256; + +union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; +typedef union _bits320 bits320; + +union _bits384 { bits256 sig; uint8_t bytes[48]; uint16_t ushorts[24]; uint32_t uints[12]; uint64_t ulongs[6]; uint64_t txid; }; +typedef union _bits384 bits384; \ No newline at end of file diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index d92ab7d3d74..6b5fde79fa7 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -85,13 +85,6 @@ Details. #define CCDISABLEALL memset(ASSETCHAINS_CCDISABLES,1,sizeof(ASSETCHAINS_CCDISABLES)) #define CCENABLE(x) ASSETCHAINS_CCDISABLES[((uint8_t)x)] = 0 -/* moved to komodo_cJSON.h -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif -*/ /// \endcond /// identifiers of additional data blobs in token opreturn script: diff --git a/src/cc/dapps/dappstd.c b/src/cc/dapps/dappstd.c index bb612c22e4c..38f7a75f739 100644 --- a/src/cc/dapps/dappstd.c +++ b/src/cc/dapps/dappstd.c @@ -22,6 +22,7 @@ #include #include #include +#include "bits256.h" extern struct games_state globalR; void *gamesiterate(struct games_state *rs); @@ -39,12 +40,6 @@ char whoami[MAXSTR]; #define KOMODO_ASSETCHAIN_MAXLEN 65 char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],IPADDRESS[100]; -#ifndef _BITS256 -#define _BITS256 -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; -#endif - #ifdef _WIN32 #ifdef _MSC_VER int gettimeofday(struct timeval * tp, struct timezone * tzp) diff --git a/src/cc/includes/curve25519.h b/src/cc/includes/curve25519.h index 657fab4d011..46d6b15a5f7 100755 --- a/src/cc/includes/curve25519.h +++ b/src/cc/includes/curve25519.h @@ -19,17 +19,7 @@ #include #include #include - -union _bits128 { uint8_t bytes[16]; uint16_t ushorts[8]; uint32_t uints[4]; uint64_t ulongs[2]; uint64_t txid; }; -typedef union _bits128 bits128; -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; - -union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; -typedef union _bits320 bits320; - -union _bits384 { bits256 sig; uint8_t bytes[48]; uint16_t ushorts[24]; uint32_t uints[12]; uint64_t ulongs[6]; uint64_t txid; }; -typedef union _bits384 bits384; +#include "bits256.h" struct sha256_vstate { uint64_t length; uint32_t state[8],curlen; uint8_t buf[64]; }; struct rmd160_vstate { uint64_t length; uint8_t buf[64]; uint32_t curlen, state[5]; }; diff --git a/src/cc/rogue/main.c b/src/cc/rogue/main.c index 29b0cf7305b..6774eb32787 100644 --- a/src/cc/rogue/main.c +++ b/src/cc/rogue/main.c @@ -23,6 +23,8 @@ #include #include +#include "bits256.h" + char USERPASS[8192]; uint16_t ROGUE_PORT; extern char Gametxidstr[67]; @@ -32,12 +34,6 @@ extern char Gametxidstr[67]; #define KOMODO_ASSETCHAIN_MAXLEN 65 char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],IPADDRESS[100]; -#ifndef _BITS256 -#define _BITS256 -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; -#endif - #ifdef _WIN32 #ifdef _MSC_VER int gettimeofday(struct timeval * tp, struct timezone * tzp) diff --git a/src/cc/rogue/rogue.h b/src/cc/rogue/rogue.h index 65ddf1e514a..960316219c9 100644 --- a/src/cc/rogue/rogue.h +++ b/src/cc/rogue/rogue.h @@ -47,6 +47,7 @@ #include "extern.h" +#include "bits256.h" #undef lines @@ -351,12 +352,6 @@ #define SATOSHIDEN ((uint64_t)100000000L) #define dstr(x) ((double)(x) / SATOSHIDEN) -#ifndef _BITS256 -#define _BITS256 -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; -#endif - #include "rogue_player.h" // interface to rpc struct rogue_state diff --git a/src/hex.h b/src/hex.h index ccc4ccde87c..1361c8bc0f2 100644 --- a/src/hex.h +++ b/src/hex.h @@ -3,18 +3,13 @@ */ #pragma once #include +#include "bits256.h" #ifdef __cplusplus extern "C" { #endif -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif - /*** * turn a char into its hex value * A '5' becomes a 5, 'B' (or 'b') becomes 11. diff --git a/src/komodo_cJSON.h b/src/komodo_cJSON.h index 3586b5cbf5b..773367caa38 100644 --- a/src/komodo_cJSON.h +++ b/src/komodo_cJSON.h @@ -46,6 +46,7 @@ #include #include +#include "bits256.h" #include "cJSON.h" //#include "../crypto777/OS_portable.h" @@ -57,12 +58,6 @@ extern "C" { #endif -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif - /* Macros for creating things quickly. */ #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) diff --git a/src/komodo_curve25519.h b/src/komodo_curve25519.h index cba40561b8b..3991daf8378 100644 --- a/src/komodo_curve25519.h +++ b/src/komodo_curve25519.h @@ -20,6 +20,8 @@ #include #include #include +#include "bits256.h" + #ifdef _WIN32 #include #endif diff --git a/src/komodo_port.c b/src/komodo_port.c index fd68db881dd..f19018eebcc 100644 --- a/src/komodo_port.c +++ b/src/komodo_port.c @@ -17,6 +17,7 @@ #include #include #include +#include "bits256.h" uint64_t ASSETCHAINS_COMMISSION; uint32_t ASSETCHAINS_MAGIC = 2387029918; @@ -24,8 +25,6 @@ uint8_t ASSETCHAINS_OVERRIDE_PUBKEY33[33]; struct sha256_vstate { uint64_t length; uint32_t state[8],curlen; uint8_t buf[64]; }; struct rmd160_vstate { uint64_t length; uint8_t buf[64]; uint32_t curlen, state[5]; }; -union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; -typedef union _bits256 bits256; // following is ported from libtom diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 6b7c316b6b9..8cf68918b91 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -48,14 +48,7 @@ #define KOMODO_KVDURATION 1440 #define KOMODO_ASSETCHAIN_MAXLEN 65 -#ifndef _BITS256 -#define _BITS256 - union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; - typedef union _bits256 bits256; -#endif - -union _bits320 { uint8_t bytes[40]; uint16_t ushorts[20]; uint32_t uints[10]; uint64_t ulongs[5]; uint64_t txid; }; -typedef union _bits320 bits320; +#include "bits256.h" struct komodo_kv { UT_hash_handle hh; bits256 pubkey; uint8_t *key,*value; int32_t height; uint32_t flags; uint16_t keylen,valuesize; }; From 035cdde106c01cea70798a4676a95404bd4a04db Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 11 Jun 2021 14:36:37 -0500 Subject: [PATCH 14/58] Add tests --- src/Makefile.ktest.include | 3 ++- src/hex.c | 21 +++++++++--------- src/test-komodo/test_hex.cpp | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 src/test-komodo/test_hex.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index bfbccc196ad..9bbd99d0ffb 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -14,7 +14,8 @@ komodo_test_SOURCES = \ test-komodo/test_sha256_crypto.cpp \ test-komodo/test_script_standard_tests.cpp \ test-komodo/test_addrman.cpp \ - test-komodo/test_netbase_tests.cpp + test-komodo/test_netbase_tests.cpp \ + test-komodo/test_hex.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/hex.c b/src/hex.c index 55d6a645337..024cba65ed5 100644 --- a/src/hex.c +++ b/src/hex.c @@ -54,40 +54,41 @@ unsigned char _decode_hex(const char *hex) /*** * Turn a hex string into bytes - * @param bytes where to store the output + * @param bytes where to store the output (will be cleared if hex has invalid chars) * @param n number of bytes to process * @param hex the input (will ignore CR/LF) - * @returns the number of bytes processed (not an indicator of success) + * @returns the number of bytes processed */ int32_t decode_hex(uint8_t *bytes, int32_t n,const char *str) { - int32_t adjust = 0; - + uint8_t extra = 0; // check validity of input if ( is_hexstr(str,n) <= 0 ) { memset(bytes,0,n); // give no results - return(n); + return 0; } - // ignore CR/LF - while(str[n-1] == '\n' || str[n-1] == '\r') - --n; + // ignore CR/LF ( this I believe is broken, commenting out for now - JMJ ) + //while(str[n-1] == '\n' || str[n-1] == '\r') + // --n; if ( n == 0 || (str[n*2+1] == 0 && str[n*2] != 0) ) { if ( n > 0 ) { + // special case: odd number of char, then null terminator + // treat first char as a whole byte bytes[0] = unhex(str[0]); + extra = 1; } bytes++; str++; - adjust = 1; } if ( n > 0 ) { for (int i=0; i +#include "hex.h" + +namespace TestHex { + + TEST(TestHex, decodehex) + { + { + // n = 0 + char* in = (char*) "01"; + uint8_t bytes[2] = {0}; + ASSERT_EQ(decode_hex(bytes, 0, in), 0); + ASSERT_EQ(bytes[0], 0x00); + } + { + // happy path + char* in = (char*) "01"; + uint8_t bytes[1] = {0}; + ASSERT_EQ(decode_hex(bytes, 1, in), 1); + ASSERT_EQ(bytes[0], 0x01); + } + { + // cr/lf + char* in = (char*) "01\r\n"; + uint8_t bytes[1] = {0}; + ASSERT_EQ(decode_hex(bytes, 1, in), 1); + ASSERT_EQ(bytes[0], 0x01); + } + { + // string longer than what we say by 1 + // evidently a special case that we handle by treating + // the 1st char as a complete byte + char* in = (char*) "010"; + uint8_t bytes[2] = {0}; + ASSERT_EQ(decode_hex(bytes, 1, in), 2); + ASSERT_EQ(bytes[0], 0); + ASSERT_EQ(bytes[1], 16); + } + } + +} // namespace TestHex From efcb5ec987539301a880799cfc2367af7144fcf1 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 11 Jun 2021 15:06:14 -0500 Subject: [PATCH 15/58] More simplification of decode_hex --- src/hex.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/hex.c b/src/hex.c index 024cba65ed5..5e8c68b7c04 100644 --- a/src/hex.c +++ b/src/hex.c @@ -54,6 +54,8 @@ unsigned char _decode_hex(const char *hex) /*** * Turn a hex string into bytes + * NOTE: If there is 1 extra character in a null-terminated str, treat the first char as a full byte + * * @param bytes where to store the output (will be cleared if hex has invalid chars) * @param n number of bytes to process * @param hex the input (will ignore CR/LF) @@ -68,18 +70,12 @@ int32_t decode_hex(uint8_t *bytes, int32_t n,const char *str) memset(bytes,0,n); // give no results return 0; } - // ignore CR/LF ( this I believe is broken, commenting out for now - JMJ ) - //while(str[n-1] == '\n' || str[n-1] == '\r') - // --n; - if ( n == 0 || (str[n*2+1] == 0 && str[n*2] != 0) ) + if (str[n*2+1] == 0 && str[n*2] != 0) { - if ( n > 0 ) - { - // special case: odd number of char, then null terminator - // treat first char as a whole byte - bytes[0] = unhex(str[0]); - extra = 1; - } + // special case: odd number of char, then null terminator + // treat first char as a whole byte + bytes[0] = unhex(str[0]); + extra = 1; bytes++; str++; } From 205b5d881b56cceea31067dadde515a721681d44 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 11 Jun 2021 15:42:36 -0500 Subject: [PATCH 16/58] Added missing include --- src/crosschain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 0a081c0868a..4b1cae233f3 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -19,6 +19,7 @@ #include "main.h" #include "notarisationdb.h" #include "merkleblock.h" +#include "hex.h" #include "cc/CCinclude.h" From 8760d1a0f0289ce357d444dc86f6929044921b78 Mon Sep 17 00:00:00 2001 From: gcharang Date: Mon, 14 Jun 2021 20:36:31 +0530 Subject: [PATCH 17/58] remove Coqui, AXO and BTCH from dPoW --- src/ac.json | 22 +--------------------- src/ac/axo | 2 -- src/ac/btch | 2 -- src/ac/coquicash | 2 -- src/assetchains.json | 19 ------------------- src/assetchains.old | 3 --- src/fiat/axo | 2 -- src/fiat/btch | 2 -- 8 files changed, 1 insertion(+), 53 deletions(-) delete mode 100755 src/ac/axo delete mode 100755 src/ac/btch delete mode 100755 src/ac/coquicash delete mode 100755 src/fiat/axo delete mode 100755 src/fiat/btch diff --git a/src/ac.json b/src/ac.json index 7ffed005a95..f0405721181 100644 --- a/src/ac.json +++ b/src/ac.json @@ -53,18 +53,6 @@ "ac_supply": "999999" } , - "COQUICASH": { - "ac_supply": "72000000", - "ac_reward": "7200000000", - "ac_staked": "50", - "ac_halving": "420000", - "ac_cc": "2", - "ac_ccenable": "227,235,236,241", - "addnode": [ - "78.47.108.168" - ] - } - , "WLC": { "ac_supply": "210000000" @@ -81,20 +69,12 @@ } , - "AXO": { - "ac_supply": "200000000", - "ac_ccactivate": "130000" - } - , + "ETOMIC": { "ac_supply": "100000000" } - , - "BTCH": { - "ac_supply": "20998641" - } , "NINJA": { diff --git a/src/ac/axo b/src/ac/axo deleted file mode 100755 index 18d38cac070..00000000000 --- a/src/ac/axo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=AXO $1 $2 $3 $4 $5 $6 diff --git a/src/ac/btch b/src/ac/btch deleted file mode 100755 index 6a57ea8d1f7..00000000000 --- a/src/ac/btch +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BTCH $1 $2 $3 $4 $5 $6 diff --git a/src/ac/coquicash b/src/ac/coquicash deleted file mode 100755 index c882b223923..00000000000 --- a/src/ac/coquicash +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=COQUICASH $1 $2 $3 $4 $5 $6 diff --git a/src/assetchains.json b/src/assetchains.json index 68486cfbe27..76dcee37ddb 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -1,9 +1,4 @@ [ - { - "ac_name": "AXO", - "ac_supply": "200000000", - "ac_ccactivate": "130000" - }, { "ac_name": "BET", "ac_supply": "999999" @@ -12,10 +7,6 @@ "ac_name": "BOTS", "ac_supply": "999999" }, - { - "ac_name": "BTCH", - "ac_supply": "20998641" - }, { "ac_name": "CCL", "ac_supply": "200000000", @@ -25,16 +16,6 @@ "spentindex": "1", "addnode": ["142.93.136.89", "195.201.22.89"] }, - { - "ac_name": "COQUICASH", - "ac_supply": "72000000", - "ac_reward": "7200000000", - "ac_staked": "50", - "ac_halving": "420000", - "ac_cc": "2", - "ac_ccenable": "227,235,236,241", - "addnode": ["78.47.108.168"] - }, { "ac_name": "CRYPTO", "ac_supply": "999999" diff --git a/src/assetchains.old b/src/assetchains.old index 26815545548..8bec3299c1c 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -4,12 +4,9 @@ delay=60 source pubkey.txt echo $pubkey -./komodod -pubkey=$pubkey -ac_name=AXO -ac_supply=200000000 -ac_ccactivate=130000 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=BET -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=BOTS -ac_supply=999999 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=BTCH -ac_supply=20998641 -addnode=95.213.238.98 & ./komodod -pubkey=$pubkey -ac_name=CCL -ac_supply=200000000 -ac_end=1 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=142.93.136.89 -addnode=195.201.22.89 $1 & -./komodod -pubkey=$pubkey -ac_name=COQUICASH -ac_supply=72000000 -ac_reward=7200000000 -ac_staked=50 -ac_halving=420000 -ac_cc=2 -ac_ccenable=227,235,236,241 -addnode=78.47.108.168 $1 & ./komodod -pubkey=$pubkey -ac_name=CRYPTO -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=DEX -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=GLEEC -ac_supply=210000000 -ac_public=1 -ac_staked=100 -addnode=95.217.161.126 $1 & diff --git a/src/fiat/axo b/src/fiat/axo deleted file mode 100755 index 18d38cac070..00000000000 --- a/src/fiat/axo +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=AXO $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/btch b/src/fiat/btch deleted file mode 100755 index 6a57ea8d1f7..00000000000 --- a/src/fiat/btch +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=BTCH $1 $2 $3 $4 $5 $6 From 25fb55796d19e3cab658972ce352dfd7a57c6f57 Mon Sep 17 00:00:00 2001 From: gcharang Date: Mon, 14 Jun 2021 20:48:53 +0530 Subject: [PATCH 18/58] remove Coqui from fiat dir --- src/fiat/coquicash | 2 -- 1 file changed, 2 deletions(-) delete mode 100755 src/fiat/coquicash diff --git a/src/fiat/coquicash b/src/fiat/coquicash deleted file mode 100755 index c882b223923..00000000000 --- a/src/fiat/coquicash +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=COQUICASH $1 $2 $3 $4 $5 $6 From 405dbc0f44e53deb472c3540dbbed4083851c640 Mon Sep 17 00:00:00 2001 From: smk762 <35845239+smk762@users.noreply.github.com> Date: Thu, 17 Jun 2021 20:34:13 +0800 Subject: [PATCH 19/58] Delete oot --- src/ac/oot | 2 -- 1 file changed, 2 deletions(-) delete mode 100755 src/ac/oot diff --git a/src/ac/oot b/src/ac/oot deleted file mode 100755 index 4c7c6b68345..00000000000 --- a/src/ac/oot +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OOT $1 $2 $3 $4 $5 $6 From ac509ae0ae1e3bcad338113cda47ef8b958c9e65 Mon Sep 17 00:00:00 2001 From: smk762 <35845239+smk762@users.noreply.github.com> Date: Thu, 17 Jun 2021 20:35:25 +0800 Subject: [PATCH 20/58] Delete oot --- src/fiat/oot | 2 -- 1 file changed, 2 deletions(-) delete mode 100755 src/fiat/oot diff --git a/src/fiat/oot b/src/fiat/oot deleted file mode 100755 index 4c7c6b68345..00000000000 --- a/src/fiat/oot +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -./komodo-cli -ac_name=OOT $1 $2 $3 $4 $5 $6 From 734fb169674dd15a911c4b0fd3229de15f6b70b3 Mon Sep 17 00:00:00 2001 From: smk762 <35845239+smk762@users.noreply.github.com> Date: Thu, 17 Jun 2021 20:35:44 +0800 Subject: [PATCH 21/58] Update assetchains.json --- src/assetchains.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/assetchains.json b/src/assetchains.json index 68486cfbe27..622ffe8c07b 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -94,12 +94,6 @@ "ac_name": "NINJA", "ac_supply": "100000000" }, - { - "ac_name": "OOT", - "ac_supply": "216000000", - "ac_sapling": "5000000", - "addnode": ["88.99.212.81"] - }, { "ac_name": "PANGEA", "ac_supply": "999999" From 5d4009fc90ce2064834258fd187339ab1eea7aac Mon Sep 17 00:00:00 2001 From: smk762 <35845239+smk762@users.noreply.github.com> Date: Thu, 17 Jun 2021 20:35:54 +0800 Subject: [PATCH 22/58] Update assetchains.old --- src/assetchains.old | 1 - 1 file changed, 1 deletion(-) diff --git a/src/assetchains.old b/src/assetchains.old index 26815545548..9093857a5bb 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -22,7 +22,6 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=MORTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -ac_staked=10 -addnode=95.217.44.58 -addnode=138.201.136.145 $1 & ./komodod -pubkey=$pubkey -ac_name=MSHARK -ac_supply=1400000 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=NINJA -ac_supply=100000000 -addnode=95.213.238.98 $1 & -./komodod -pubkey=$pubkey -ac_name=OOT -ac_supply=216000000 -ac_sapling=5000000 -addnode=88.99.212.81 $1 & ./komodod -pubkey=$pubkey -ac_name=PANGEA -ac_supply=999999 -addnode=95.213.238.98 $1 & ./komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=88.99.212.81 $1 & ./komodod -pubkey=$pubkey -ac_name=REVS -ac_supply=1300000 -addnode=95.213.238.98 $1 & From 322aba0ed783867b227b99187a8b8aec7e14c172 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 21 Jun 2021 15:19:15 -0500 Subject: [PATCH 23/58] compile -O0 when DEBUG --- .gitignore | 2 +- depends/hosts/linux.mk | 5 ++--- src/cc/Makefile_custom | 49 ++++++++++++++++++------------------------ zcutil/build.sh | 3 ++- 4 files changed, 26 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 2f85c6d195f..f875a16f921 100644 --- a/.gitignore +++ b/.gitignore @@ -161,5 +161,5 @@ Makefile.in configure doc/man/Makefile.in src/Makefile.in -src/cc/customcc.so +src/cc/libcc.so src/libcc.so diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk index 31748d66226..08a30684d13 100644 --- a/depends/hosts/linux.mk +++ b/depends/hosts/linux.mk @@ -1,12 +1,11 @@ linux_CFLAGS=-pipe linux_CXXFLAGS=$(linux_CFLAGS) -linux_release_CFLAGS=-O1 +linux_release_CFLAGS=-O3 linux_release_CXXFLAGS=$(linux_release_CFLAGS) -linux_debug_CFLAGS=-O1 +linux_debug_CFLAGS=-g -O0 linux_debug_CXXFLAGS=$(linux_debug_CFLAGS) - linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC ifeq (86,$(findstring 86,$(build_arch))) diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index 79219ec96c1..36409a7292a 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -1,38 +1,31 @@ -SHELL = /bin/sh -CC = gcc -CC_DARWIN = g++-8 -CC_WIN = x86_64-w64-mingw32-gcc-posix -CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib -CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -CFLAGS_WIN = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -DEBUGFLAGS = -O0 -D _DEBUG -RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program -$(info $(OS)) +SHELL = /bin/sh OS := $(shell uname -s) -$(info $(OS)) -TARGET = customcc.so -TARGET_DARWIN = customcc.dylib -TARGET_WIN = customcc.dll + +ifeq ($(OS),Darwin) + CC = g++-8 + CFLAGS = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib + TARGET = libcc.dylib +else + ifeq ($(OS),Linux) + CC = gcc + CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared + TARGET = libcc.so + else + CC = x86_64-w64-mingw32-gcc-posix + CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared + TARGET = libcc.dll + endif +endif + +DEBUGFLAGS =-g -O0 -D _DEBUG +#RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program SOURCES = cclib.cpp -#HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ all: $(TARGET) $(TARGET): $(SOURCES) - $(info Building cclib to src/) -ifeq ($(OS),Darwin) - $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES) - cp $(TARGET_DARWIN) ../libcc.dylib -else ifeq ($(HOST),x86_64-w64-mingw32) - $(info WINDOWS) - $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES) - cp $(TARGET_WIN) ../libcc.dll -#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host -else - $(info LINUX) $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) - cp $(TARGET) ../libcc.so -endif + cp $(TARGET) ../$(TARGET) clean: rm -rf $(TARGET) diff --git a/zcutil/build.sh b/zcutil/build.sh index 6f625b185aa..891dee65bfd 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -96,10 +96,11 @@ eval "$MAKE" --version as --version ld -v +# Build the config.site file HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" #BUILD CCLIB From 98f49cc7221b43e03d74107c50288057c81ee152 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 22 Jun 2021 14:40:43 -0500 Subject: [PATCH 24/58] compile cryptoconditions via autotools --- src/Makefile.am | 45 ++++++++++++++++++++++----------------------- zcutil/build.sh | 11 ----------- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 23cff51cba9..659d223cf42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,6 +52,7 @@ LIBSECP256K1=secp256k1/libsecp256k1.la LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la +LIBCC=libcc.la LIBZCASH=libzcash.a if ENABLE_ZMQ @@ -72,6 +73,7 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) LIBSNARK_CXXFLAGS = $(AM_CXXFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1 +LIBSNARK_OPTFLAGS = $(CPPFLAGS) -march=x86-64 if HAVE_OPENMP LIBSNARK_CONFIG_FLAGS += MULTICORE=1 endif @@ -80,7 +82,7 @@ LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif $(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" libsnark-tests: $(wildcard snark/src/*) $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" @@ -113,7 +115,7 @@ if ENABLE_PROTON EXTRA_LIBRARIES += $(LIBBITCOIN_PROTON) endif -lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) +lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) $(LIBCC) bin_PROGRAMS = noinst_PROGRAMS = @@ -503,6 +505,11 @@ libbitcoin_common_a_SOURCES = \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) +# a shared library for cryptoconditions +libcc_la_SOURCES = cc/cclib.cpp +libcc_la_CPPFLAGS = -DBUILD_CUSTOMCC -I../secp256k1/include -I../depends/$(shell echo `../depends/config.guess`/include) -I./univalue/include -I./cryptoconditions/include -I./cryptoconditions/src -I./cryptoconditions/src/asn -I. -I./cc +libcc_la_LDFLAGS = -version-info 0:0:0 + # util: shared between all executables. # This library *must* be included to make sure that the glibc # backward-compatibility objects and their sanity checks are linked. @@ -591,17 +598,8 @@ komodod_LDADD += \ $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ - $(LIBZCASH_LIBS) - -if TARGET_DARWIN -komodod_LDADD += libcc.dylib $(LIBSECP256K1) -endif -if TARGET_WINDOWS -komodod_LDADD += libcc.dll $(LIBSECP256K1) -endif -if TARGET_LINUX -komodod_LDADD += libcc.so $(LIBSECP256K1) -endif + $(LIBZCASH_LIBS) \ + $(LIBCC) if ENABLE_PROTON komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) @@ -690,7 +688,6 @@ komodo_tx_LDADD = \ $(LIBCRYPTOCONDITIONS) komodo_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) -# # zcash protocol primitives # libzcash_a_SOURCES = \ @@ -702,7 +699,7 @@ libzcash_a_SOURCES = \ zcash/Note.cpp \ zcash/prf.cpp \ zcash/util.cpp \ - zcash/zip32.cpp \ + zcash/zip32.cpp \ zcash/circuit/commitment.tcc \ zcash/circuit/gadget.tcc \ zcash/circuit/merkle.tcc \ @@ -710,15 +707,17 @@ libzcash_a_SOURCES = \ zcash/circuit/prfs.tcc \ zcash/circuit/utils.tcc -libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) $(HARDENED_CXXFLAGS) $(HARDENED_LDFLAGS) -pipe $(SAN_LDFLAGS) -O1 -g -Wstack-protector $(SAN_CXXFLAGS) -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) - -#libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -#libzcash_a_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -#libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMONTGOMERY_OUTPUT - +libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 \ + -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) \ + $(HARDENED_CXXFLAGS) $(HARDENED_LDFLAGS) -pipe $(SAN_LDFLAGS) \ + -Wstack-protector $(SAN_CXXFLAGS) -fstack-protector-all \ + -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) libzcash_a_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing libzcash_a_LDFLAGS = $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) libzcash_a_CPPFLAGS += -DMONTGOMERY_OUTPUT +#libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +#libzcash_a_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +#libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMONTGOMERY_OUTPUT # zcashconsensus library # if BUILD_BITCOIN_LIBS @@ -761,7 +760,7 @@ EXTRA_DIST = leveldb snark clean-local: -$(MAKE) -C leveldb clean -$(MAKE) -C secp256k1 clean - -$(MAKE) -C snark clean + -$(MAKE) -C snark clean-all -$(MAKE) -C univalue clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h @@ -791,7 +790,7 @@ endif $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( Date: Tue, 22 Jun 2021 15:14:13 -0500 Subject: [PATCH 25/58] Move hardfork consts to separate header --- src/komodo_defs.h | 420 --------------------------------------- src/komodo_globals.h | 1 + src/komodo_hardfork.h | 424 ++++++++++++++++++++++++++++++++++++++++ src/komodo_notary.h | 1 + src/notaries_staked.cpp | 1 + 5 files changed, 427 insertions(+), 420 deletions(-) create mode 100644 src/komodo_hardfork.h diff --git a/src/komodo_defs.h b/src/komodo_defs.h index b4b118a5760..a633f797858 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -46,424 +46,6 @@ // 7113400 = 5x current KMD blockheight. // to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. -#define NUM_KMD_SEASONS 6 -#define NUM_KMD_NOTARIES 64 - -extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork -extern const int32_t nDecemberHardforkHeight; //December 2019 hardfork - -extern const uint32_t nS4Timestamp; //dPoW Season 4 2020 hardfork -extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork - -extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) -extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) - -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; - -// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. -static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = -{ - { - { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, - { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, - { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, - { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, - { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 - { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, - { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, - { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, - { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, - { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 - { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, - { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, - { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, - { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, - { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 - { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, - { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, - { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, - { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 - { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, - { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, - { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, - { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, - { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, - { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, - { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, - { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 - { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, - { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, - { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, - { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, - { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, - { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, - { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, - { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 - { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, - { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, - { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, - { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, - { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, - { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, - { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, - { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, - { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, - { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 - { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, - { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } - }, - { - {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, - {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, - {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, - {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 - {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, - {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, - {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, - {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, - {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, - {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, - {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 - {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, - {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, - {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, - {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, - {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, - {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, - {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, - {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, - {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, - {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, - {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, - {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, - {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 - {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, - {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, - {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, - {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, - {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, - {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 - {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, - {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, - {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, - {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, - {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, - {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, - {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, - {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, - {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 - {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, - {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, - {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - }, - { - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 3.5 - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 4 - { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, - { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, - { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, - { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, - { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, - { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, - { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, - { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, - { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, - { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, - { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, - { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, - { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, - { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, - { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, - { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, - { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, - { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, - { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, - { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, - { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, - { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, - { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, - { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, - { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, - { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, - { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, - { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, - { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, - { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, - { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, - { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, - { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, - { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, - { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, - { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, - { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, - { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, - { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, - { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, - { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, - { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, - { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, - { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, - { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, - { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, - { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, - { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, - { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, - { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, - { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, - { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } - }, - { - // Season 5 - {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, - {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, - {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, - {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, - {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, - {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, - {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, - {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, - {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, - {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 - {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, - {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, - {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, - {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, - {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, - {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, - {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, - {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, - {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 - {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, - {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, - {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, - {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, - {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, - {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, - {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, - {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, - {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, - {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 - {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, - {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, - {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, - {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, - {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, - {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, - {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, - {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, - {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 - {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, - {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, - {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, - {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, - {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, - {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, - {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, - {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, - {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, - {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 - {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, - {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, - {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, - {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, - {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, - {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, - {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, - {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, - {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 - {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, - {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, - {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} - } -}; #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) #define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7))) @@ -517,8 +99,6 @@ extern int32_t VERUS_MIN_STAKEAGE; extern std::string DONATION_PUBKEY; extern uint8_t ASSETCHAINS_PRIVATE; extern int32_t USE_EXTERNAL_PUBKEY; -extern char NOTARYADDRS[64][64]; -extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; extern int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL,IS_STAKED_NOTARY,STAKED_ERA; extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT; extern int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 063364230e5..45dbed084ef 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -14,6 +14,7 @@ ******************************************************************************/ #include "komodo_defs.h" +#include "komodo_hardfork.h" void komodo_prefetch(FILE *fp); uint32_t komodo_heightstamp(int32_t height); diff --git a/src/komodo_hardfork.h b/src/komodo_hardfork.h new file mode 100644 index 00000000000..6cb796d8f12 --- /dev/null +++ b/src/komodo_hardfork.h @@ -0,0 +1,424 @@ +#pragma once +#include + +#define NUM_KMD_SEASONS 6 +#define NUM_KMD_NOTARIES 64 + +extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork +extern const int32_t nDecemberHardforkHeight; //December 2019 hardfork + +extern const uint32_t nS4Timestamp; //dPoW Season 4 2020 hardfork +extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork + +extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) +extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) + +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; + +// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. +static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = +{ + { + { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 + { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, + { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, + { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 + { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, + { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, + { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, + { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, + { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 + { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, + { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, + { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 + { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, + { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, + { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, + { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, + { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, + { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 + { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 + { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, + { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, + { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, + { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, + { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, + { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 + { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, + { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } + }, + { + {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, + {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, + {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, + {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 + {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, + {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, + {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, + {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, + {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, + {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, + {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 + {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, + {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, + {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, + {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, + {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, + {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, + {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, + {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, + {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, + {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, + {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, + {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, + {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 + {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, + {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, + {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, + {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, + {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, + {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 + {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, + {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, + {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, + {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, + {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, + {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, + {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, + {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, + {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 + {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, + {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, + {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + }, + { + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 3.5 + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 4 + { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, + { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, + { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, + { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, + { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, + { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, + { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, + { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, + { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, + { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, + { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, + { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, + { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, + { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, + { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, + { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, + { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, + { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, + { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, + { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, + { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, + { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, + { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, + { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, + { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, + { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, + { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, + { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, + { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, + { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, + { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, + { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, + { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, + { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, + { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, + { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, + { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, + { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, + { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, + { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, + { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, + { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, + { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, + { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, + { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, + { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, + { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, + { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, + { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, + { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, + { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, + { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } + }, + { + // Season 5 + {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, + {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, + {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, + {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, + {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, + {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, + {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, + {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, + {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, + {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 + {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, + {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, + {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, + {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, + {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, + {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, + {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, + {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, + {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 + {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, + {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, + {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, + {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, + {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, + {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, + {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, + {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, + {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, + {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 + {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, + {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, + {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, + {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, + {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, + {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, + {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, + {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, + {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 + {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, + {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, + {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, + {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, + {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, + {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, + {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, + {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, + {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, + {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 + {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, + {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, + {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, + {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, + {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, + {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, + {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, + {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, + {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 + {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, + {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, + {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} + } +}; + +extern char NOTARYADDRS[64][64]; +extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; \ No newline at end of file diff --git a/src/komodo_notary.h b/src/komodo_notary.h index f820e0bd568..00094389da7 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -18,6 +18,7 @@ #include "komodo_cJSON.h" #include "notaries_staked.h" +#include "komodo_hardfork.h" #define KOMODO_MAINNET_START 178999 #define KOMODO_NOTARIES_HEIGHT1 814000 diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index db1696ed5ec..8ab48cebbc6 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -3,6 +3,7 @@ #include "crosschain.h" #include "cc/CCinclude.h" #include "komodo_defs.h" +#include "komodo_hardfork.h" #include extern pthread_mutex_t staked_mutex; From d5ad986dcccf46644cd758d12136e2fede7475d1 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 22 Jun 2021 15:50:38 -0500 Subject: [PATCH 26/58] tweak make clean --- src/Makefile.am | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 659d223cf42..e95e3a3e8c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -760,11 +760,15 @@ EXTRA_DIST = leveldb snark clean-local: -$(MAKE) -C leveldb clean -$(MAKE) -C secp256k1 clean - -$(MAKE) -C snark clean-all + -$(MAKE) -C snark clean -$(MAKE) -C univalue clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h +clean-all: clean-local + -$(MAKE) -C snark clean-all + -$(MAKE) -C univalue clean-all + .rc.o: @test -f $(WINDRES) $(AM_V_GEN) $(WINDRES) -DWINDRES_PREPROC -i $< -o $@ @@ -790,7 +794,7 @@ endif $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( Date: Tue, 22 Jun 2021 15:52:33 -0500 Subject: [PATCH 27/58] Revert changes to cc makefile --- src/cc/Makefile_custom | 49 ++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index 36409a7292a..79219ec96c1 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -1,31 +1,38 @@ -SHELL = /bin/sh +SHELL = /bin/sh +CC = gcc +CC_DARWIN = g++-8 +CC_WIN = x86_64-w64-mingw32-gcc-posix +CFLAGS_DARWIN = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib +CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared +CFLAGS_WIN = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared +DEBUGFLAGS = -O0 -D _DEBUG +RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program +$(info $(OS)) OS := $(shell uname -s) - -ifeq ($(OS),Darwin) - CC = g++-8 - CFLAGS = -DBUILD_CUSTOMCC -std=c++11 -arch x86_64 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib - TARGET = libcc.dylib -else - ifeq ($(OS),Linux) - CC = gcc - CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared - TARGET = libcc.so - else - CC = x86_64-w64-mingw32-gcc-posix - CFLAGS = -Wno-write-strings -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared - TARGET = libcc.dll - endif -endif - -DEBUGFLAGS =-g -O0 -D _DEBUG -#RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program +$(info $(OS)) +TARGET = customcc.so +TARGET_DARWIN = customcc.dylib +TARGET_WIN = customcc.dll SOURCES = cclib.cpp +#HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ all: $(TARGET) $(TARGET): $(SOURCES) + $(info Building cclib to src/) +ifeq ($(OS),Darwin) + $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES) + cp $(TARGET_DARWIN) ../libcc.dylib +else ifeq ($(HOST),x86_64-w64-mingw32) + $(info WINDOWS) + $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES) + cp $(TARGET_WIN) ../libcc.dll +#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host +else + $(info LINUX) $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) - cp $(TARGET) ../$(TARGET) + cp $(TARGET) ../libcc.so +endif clean: rm -rf $(TARGET) From 6f9ff06b4d77188eb9548b79e29d4ffab5751883 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 23 Jun 2021 09:23:56 -0500 Subject: [PATCH 28/58] finer control of build output --- src/Makefile.am | 6 +++--- src/leveldb/Makefile | 12 ++++++------ src/secp256k1/Makefile.am | 4 ++-- src/snark/Makefile | 10 +++++----- zcutil/build.sh | 18 ++++++++++-------- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index e95e3a3e8c8..19fc8924b73 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ LIBMEMENV += $(builddir)/leveldb/libmemenv.a $(LIBLEVELDB): $(LIBMEMENV) $(LIBLEVELDB) $(LIBMEMENV): - @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ + $(AM_V_at)$(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \ OPT="$(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -D__STDC_LIMIT_MACROS" endif @@ -82,10 +82,10 @@ LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif $(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" + $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile index 2bd2cadcdde..486802d5424 100644 --- a/src/leveldb/Makefile +++ b/src/leveldb/Makefile @@ -107,8 +107,8 @@ clean: -rm -rf ios-x86/* ios-arm/* $(LIBRARY): $(LIBOBJECTS) - rm -f $@ - $(AR) -rs $@ $(LIBOBJECTS) + @rm -f $@ + @$(AR) -rs $@ $(LIBOBJECTS) db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) $(CXX) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(LIBS) @@ -189,8 +189,8 @@ write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) $(CXX) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) $(MEMENVLIBRARY) : $(MEMENVOBJECTS) - rm -f $@ - $(AR) -rs $@ $(MEMENVOBJECTS) + @rm -f $@ + @$(AR) -rs $@ $(MEMENVOBJECTS) memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) $(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS) @@ -220,8 +220,8 @@ IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64 else .cc.o: - $(CXX) $(CXXFLAGS) -c $< -o $@ + @$(CXX) $(CXXFLAGS) -c $< -o $@ .c.o: - $(CC) $(CFLAGS) -c $< -o $@ + @$(CC) $(CFLAGS) -c $< -o $@ endif diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index c5fa00fc575..bf4d448bd03 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -153,10 +153,10 @@ CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function gen_context_OBJECTS = gen_context.o gen_context_BIN = gen_context$(BUILD_EXEEXT) gen_%.o: src/gen_%.c - $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ + $(AM_V_at)$(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ $(gen_context_BIN): $(gen_context_OBJECTS) - $(CC_FOR_BUILD) $^ -o $@ + $(AM_V_at)$(CC_FOR_BUILD) $^ -o $@ $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h diff --git a/src/snark/Makefile b/src/snark/Makefile index 3ef82ab878a..26fd3ec356c 100644 --- a/src/snark/Makefile +++ b/src/snark/Makefile @@ -195,7 +195,7 @@ $(DEPINST_EXISTS): -include $(patsubst %.o,%.d, $(LIB_OBJS) $(GTEST_OBJS) $(EXEC_OBJS) ) $(LIB_OBJS) $(if $(NO_GTEST),,$(GTEST_OBJS)) $(EXEC_OBJS): %.o: %.cpp - $(CXX) -o $@ $< -c -MMD $(CXXFLAGS) + @$(CXX) -o $@ $< -c -MMD $(CXXFLAGS) LIBGTEST_A = $(DEPINST)/lib/libgtest.a @@ -205,12 +205,12 @@ $(LIBGTEST_A): $(GTESTDIR)/libsnark/gtest-all.cc $(DEPINST_EXISTS) # libsnark.a will contains all of our relevant object files, and we also mash in the .a files of relevant dependencies built by ./prepare-depends.sh $(LIBSNARK_A): $(LIB_OBJS) $(AR_LIBS) - $(AR) q $(LIBSNARK_A) $(LIB_OBJS) - if [ -n "$(AR_LIBS)" ]; then mkdir -p tmp-ar; cd tmp-ar; for AR_LIB in $(AR_LIBS); do $(AR) x $$AR_LIB; done; $(AR) qc $(LIBSNARK_A) tmp-ar/*; cd ..; rm -r tmp-ar; fi; - $(AR) s $(LIBSNARK_A) + @$(AR) q $(LIBSNARK_A) $(LIB_OBJS) + @if [ -n "$(AR_LIBS)" ]; then mkdir -p tmp-ar; cd tmp-ar; for AR_LIB in $(AR_LIBS); do $(AR) x $$AR_LIB; done; $(AR) qc $(LIBSNARK_A) tmp-ar/*; cd ..; rm -r tmp-ar; fi; + @$(AR) s $(LIBSNARK_A) libsnark.so: $(LIBSNARK_A) $(DEPINST_EXISTS) - $(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS) + @$(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS) libsnark/gadgetlib2/tests/gadgetlib2_test: \ libsnark/gadgetlib2/tests/adapters_UTEST.cpp \ diff --git a/zcutil/build.sh b/zcutil/build.sh index 206ca0738aa..1276e0ef355 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -59,8 +59,6 @@ EOF exit 0 fi -set -x - # If --enable-lcov is the first argument, enable lcov coverage support: LCOV_ARG='' HARDENING_ARG='--enable-hardening' @@ -92,14 +90,18 @@ then shift fi -eval "$MAKE" --version -as --version -ld -v +if [[ -z "${VERBOSE-}" ]]; then + VERBOSITY="--enable-silent-rules" +else + VERBOSITY="--disable-silent-rules" + set -x +fi # Build the config.site file -HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 +HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ + ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure $VERBOSITY "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" -"$MAKE" "$@" V=1 +"$MAKE" "$@" From 1a874177fc33b3dafb985a5c3766f60201edee08 Mon Sep 17 00:00:00 2001 From: lightspeed393 Date: Tue, 13 Jul 2021 12:09:27 -0400 Subject: [PATCH 29/58] Remove Benny Fairbank as a contact in Code of Conduct. --- code_of_conduct.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/code_of_conduct.md b/code_of_conduct.md index c4592cc325a..a5caabf68c9 100644 --- a/code_of_conduct.md +++ b/code_of_conduct.md @@ -48,7 +48,6 @@ You may send reports to [our Conduct email](mailto:developer@komodoplatform.com) If you wish to contact specific maintainers directly, the following have made themselves available for conduct issues: -- Benny Fairbank (benny at komodoplatform.com) - Support Team (support at komodoplatform.com) - ca333 (ca333 at komodoplatform.com) @@ -58,4 +57,3 @@ version 1.3.0, available at [homepage]: https://www.contributor-covenant.org [version]: https://www.contributor-covenant.org/version/1/3/0/ - From bc6f79ddc853f98a3ef8f9c48b84fabc6216b5e8 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 9 Aug 2021 09:30:20 -0500 Subject: [PATCH 30/58] Move c util impls to c specific obj --- src/komodo_cutils.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++ src/komodo_cutils.h | 8 ++++++ src/komodo_utils.cpp | 57 ----------------------------------------- src/komodo_utils.h | 6 ----- 4 files changed, 67 insertions(+), 63 deletions(-) diff --git a/src/komodo_cutils.cpp b/src/komodo_cutils.cpp index 74c9f6bcadc..56f2aa1806f 100644 --- a/src/komodo_cutils.cpp +++ b/src/komodo_cutils.cpp @@ -1,6 +1,65 @@ #include "komodo_cutils.h" #include "stdlib.h" //malloc + +char hexbyte(int32_t c) +{ + c &= 0xf; + if ( c < 10 ) + return('0'+c); + else if ( c < 16 ) + return('a'+c-10); + else return(0); +} + +int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len) +{ + int32_t i; + if ( len <= 0 ) + { + hexbytes[0] = 0; + return(1); + } + for (i=0; i>4) & 0xf); + hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); + //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); + } + hexbytes[len*2] = 0; + //printf("len.%ld\n",len*2+1); + return((int32_t)len*2+1); +} + +char *bits256_str(char hexstr[65],bits256 x) +{ + init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); + return(hexstr); +} + +int32_t safecopy(char *dest,char *src,long len) +{ + int32_t i = -1; + if ( src != 0 && dest != 0 && src != dest ) + { + if ( dest != 0 ) + memset(dest,0,len); + for (i=0; i= '0' && c <= '9' ) diff --git a/src/komodo_cutils.h b/src/komodo_cutils.h index a310b57ecbb..fa5ebf1d397 100644 --- a/src/komodo_cutils.h +++ b/src/komodo_cutils.h @@ -14,6 +14,14 @@ union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uin typedef union _bits256 bits256; #endif +char hexbyte(int32_t c); + +int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len); + +char *bits256_str(char hexstr[65],bits256 x); + +int32_t safecopy(char *dest,char *src,long len); + unsigned char _decode_hex(char *hex); int32_t unhex(char c); diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index 20f7651fbd1..074aeaad353 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -560,41 +560,6 @@ int32_t bitweight(uint64_t x) return(wt); } -char hexbyte(int32_t c) -{ - c &= 0xf; - if ( c < 10 ) - return('0'+c); - else if ( c < 16 ) - return('a'+c-10); - else return(0); -} - -int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len) -{ - int32_t i; - if ( len <= 0 ) - { - hexbytes[0] = 0; - return(1); - } - for (i=0; i>4) & 0xf); - hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); - //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); - } - hexbytes[len*2] = 0; - //printf("len.%ld\n",len*2+1); - return((int32_t)len*2+1); -} - -char *bits256_str(char hexstr[65],bits256 x) -{ - init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); - return(hexstr); -} - int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp) { int32_t i; uint64_t x; @@ -762,28 +727,6 @@ int64_t komodo_block_unlocktime(uint32_t nHeight) return ((int64_t)unlocktime); } -int32_t safecopy(char *dest,char *src,long len) -{ - int32_t i = -1; - if ( src != 0 && dest != 0 && src != dest ) - { - if ( dest != 0 ) - memset(dest,0,len); - for (i=0; i Date: Mon, 9 Aug 2021 15:11:05 -0500 Subject: [PATCH 31/58] add event_rewind --- src/komodo_events.cpp | 174 +++++++++++++++++++++++++---------------- src/komodo_events.h | 2 - src/komodo_structs.cpp | 14 ++++ src/komodo_structs.h | 10 ++- 4 files changed, 129 insertions(+), 71 deletions(-) diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index 946549bc9d4..4d8adf85f38 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -19,102 +19,133 @@ #include "komodo_pax.h" // komodo_pvals #include "komodo_gateway.h" // komodo_opreturn -struct komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen) +/***** + * Add a notarized event to the collection + * @param sp the state to add to + * @param symbol + * @param height + * @param dest + * @param notarized_hash + * @param notarized_desttxid + * @param notarizedheight + * @param MoM + * @param MoMdepth + */ +void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash, + uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) { - struct komodo_event *ep=0; uint16_t len = (uint16_t)(sizeof(*ep) + datalen); - if ( sp != 0 && ASSETCHAINS_SYMBOL[0] != 0 ) - { - std::lock_guard lock(komodo_mutex); - ep = (struct komodo_event *)calloc(1,len); - ep->len = len; - ep->height = height; - ep->type = type; - strcpy(ep->symbol,symbol); - if ( datalen != 0 ) - memcpy(ep->space,data,datalen); - sp->Komodo_events = (struct komodo_event **)realloc(sp->Komodo_events,(1 + sp->Komodo_numevents) * sizeof(*sp->Komodo_events)); - sp->Komodo_events[sp->Komodo_numevents++] = ep; - } - return(ep); -} + char *coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; -void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) -{ - static uint32_t counter; int32_t verified=0; char *coin; struct komodo_event_notarized N; - coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; - if ( IS_KOMODO_NOTARY != 0 && (verified= komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid)) < 0 ) + if ( IS_KOMODO_NOTARY != 0 + && komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid) < 0 ) { + static uint32_t counter; if ( counter++ < 100 ) - printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n",ASSETCHAINS_SYMBOL,height,notarizedheight,dest); + printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n", + ASSETCHAINS_SYMBOL,height,notarizedheight,dest); } else if ( strcmp(symbol,coin) == 0 ) { - if ( 0 && IS_KOMODO_NOTARY != 0 && verified != 0 ) - fprintf(stderr,"validated [%s] ht.%d notarized %d\n",coin,height,notarizedheight); - memset(&N,0,sizeof(N)); - N.blockhash = notarized_hash; - N.desttxid = notarized_desttxid; - N.notarizedheight = notarizedheight; - N.MoM = MoM; - N.MoMdepth = MoMdepth; - strncpy(N.dest,dest,sizeof(N.dest)-1); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_NOTARIZED,(uint8_t *)&N,sizeof(N)); + std::shared_ptr n = std::make_shared(); + n->blockhash = notarized_hash; + n->desttxid = notarized_desttxid; + n->notarizedheight = notarizedheight; + n->MoM = MoM; + n->MoMdepth = MoMdepth; + strncpy(n->dest, dest, sizeof(n->dest)-1); + sp->add_event(symbol, height, n); if ( sp != 0 ) komodo_notarized_update(sp,height,notarizedheight,notarized_hash,notarized_desttxid,MoM,MoMdepth); } } +/***** + * Add a pubkeys event to the collection + * @param sp where to add + * @param symbol + * @param height + * @param num + * @param pubkeys + */ void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]) { - struct komodo_event_pubkeys P; - //printf("eventadd pubkeys ht.%d\n",height); - memset(&P,0,sizeof(P)); - P.num = num; - memcpy(P.pubkeys,pubkeys,33 * num); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_RATIFY,(uint8_t *)&P,(int32_t)(sizeof(P.num) + 33 * num)); + std::shared_ptr p = std::make_shared(); + p->num = num; + memcpy(p->pubkeys, pubkeys, 33 * num); + sp->add_event(symbol, height, p); if ( sp != 0 ) komodo_notarysinit(height,pubkeys,num); } +/******** + * Add a pricefeed event to the collection + * @param sp where to add + * @param symbol + * @param height + * @param prices + * @param num + */ void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num) { - struct komodo_event_pricefeed F; - if ( num == sizeof(F.prices)/sizeof(*F.prices) ) + std::shared_ptr f = std::make_shared(); + if ( num == sizeof(f->prices)/sizeof(*f->prices) ) { - memset(&F,0,sizeof(F)); - F.num = num; - memcpy(F.prices,prices,sizeof(*F.prices) * num); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_PRICEFEED,(uint8_t *)&F,(int32_t)(sizeof(F.num) + sizeof(*F.prices) * num)); + f->num = num; + memcpy(f->prices, prices, sizeof(*f->prices) * num); + sp->add_event(symbol, height, f); if ( sp != 0 ) komodo_pvals(height,prices,num); - } //else fprintf(stderr,"skip pricefeed[%d]\n",num); + } } -void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen) +/***** + * Add an opreturn event to the collection + * @param sp where to add + * @param symbol + * @param height + * @param txid + * @param value + * @param vout + * @param buf + * @param opretlen + */ +void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid, + uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen) { - struct komodo_event_opreturn O; uint8_t *opret; if ( ASSETCHAINS_SYMBOL[0] != 0 ) { - opret = (uint8_t *)calloc(1,sizeof(O) + opretlen + 16); - O.txid = txid; - O.value = value; - O.vout = vout; - memcpy(opret,&O,sizeof(O)); - memcpy(&opret[sizeof(O)],buf,opretlen); - O.oplen = (int32_t)(opretlen + sizeof(O)); - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_OPRETURN,opret,O.oplen); + std::shared_ptr o = std::make_shared(); + // build a storage area + // JMJ TODO: This looks like a bad idea. Evaluate this code to see if a better way can be found (vector of bytes?) + uint8_t *opret = (uint8_t *)calloc(1,sizeof(komodo::event_opreturn) + opretlen + 16); + o->txid = txid; + o->value = value; + o->vout = vout; + memcpy(opret, o.get(), sizeof(komodo::event_opreturn)); + memcpy(&opret[sizeof(komodo::event_opreturn)], buf, opretlen); + o->oplen = opretlen + sizeof(komodo_event_opreturn); + sp->add_event(symbol, height, o); free(opret); if ( sp != 0 ) komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); } } +/***** + * @brief Undo an event + * @note seems to only work for KMD height events + * @param sp the state object + * @param ep the event to undo + */ void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) { switch ( ep->type ) { - case KOMODO_EVENT_RATIFY: printf("rewind of ratify, needs to be coded.%d\n",ep->height); break; - case KOMODO_EVENT_NOTARIZED: break; + case KOMODO_EVENT_RATIFY: + printf("rewind of ratify, needs to be coded.%d\n",ep->height); + break; + case KOMODO_EVENT_NOTARIZED: + break; case KOMODO_EVENT_KMDHEIGHT: if ( ep->height <= sp->SAVEDHEIGHT ) sp->SAVEDHEIGHT = ep->height; @@ -128,6 +159,7 @@ void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) } } + void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) { struct komodo_event *ep; @@ -145,7 +177,6 @@ void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) { if ( ep->height < height ) break; - //printf("[%s] undo %s event.%c ht.%d for rewind.%d\n",ASSETCHAINS_SYMBOL,symbol,ep->type,ep->height,height); komodo_event_undo(sp,ep); sp->Komodo_numevents--; } @@ -167,22 +198,29 @@ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t time } } +/****** + * @brief handle a height change event (forward or rewind) + * @param sp + * @param symbol + * @param height + * @param kmdheight + * @param timestamp + */ void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp) { - uint32_t buf[2]; - if ( kmdheight > 0 ) + if ( kmdheight > 0 ) // height is advancing { - buf[0] = (uint32_t)kmdheight; - buf[1] = timestamp; - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_KMDHEIGHT,(uint8_t *)buf,sizeof(buf)); + std::shared_ptr e = std::shared_ptr(); + e->timestamp = timestamp; + e->kheight = kmdheight; + sp->add_event(symbol, height, e); if ( sp != 0 ) komodo_setkmdheight(sp,kmdheight,timestamp); } - else + else // rewinding { - //fprintf(stderr,"REWIND kmdheight.%d\n",kmdheight); - kmdheight = -kmdheight; - komodo_eventadd(sp,height,symbol,KOMODO_EVENT_REWIND,(uint8_t *)&height,sizeof(height)); + std::shared_ptr e = std::shared_ptr(); + sp->add_event(symbol, height, e); if ( sp != 0 ) komodo_event_rewind(sp,symbol,height); } diff --git a/src/komodo_events.h b/src/komodo_events.h index bfbf9c27918..4c4fc354c8a 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -16,8 +16,6 @@ #include "komodo_defs.h" #include "komodo_structs.h" -komodo_event *komodo_eventadd(struct komodo_state *sp,int32_t height,char *symbol,uint8_t type,uint8_t *data,uint16_t datalen); - void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth); void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]); diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 430644781aa..96b5c44914b 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -163,6 +163,9 @@ std::ostream& operator<<(std::ostream& os, const event& in) case(EVENT_PRICEFEED): os << "V"; break; + case(EVENT_REWIND): + os << "B"; + break; } os << serializable(in.height); return os; @@ -192,6 +195,17 @@ std::ostream& operator<<(std::ostream& os, const event_pubkeys& in) return os; } +event_rewind::event_rewind(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_REWIND, height) +{ + // nothing to do +} +std::ostream& operator<<(std::ostream& os, const event_rewind& in) +{ + const event& e = dynamic_cast(in); + os << e; + return os; +} + event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, bool includeMoM) : event(EVENT_NOTARIZED, height) { mem_read(this->notarizedheight, data, pos, data_len); diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 9deef078a0a..7846e4ceeed 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -88,7 +88,8 @@ enum komodo_event_type EVENT_U, EVENT_KMDHEIGHT, EVENT_OPRETURN, - EVENT_PRICEFEED + EVENT_PRICEFEED, + EVENT_REWIND }; /*** @@ -113,6 +114,13 @@ class event }; std::ostream& operator<<(std::ostream& os, const event& in); +struct event_rewind : public event +{ + event_rewind() : event(komodo_event_type::EVENT_REWIND, 0) {} + event_rewind(uint8_t* data, long &pos, long data_len, int32_t height); +}; +std::ostream& operator<<(std::ostream& os, const event_rewind& in); + struct event_notarized : public event { event_notarized() : event(komodo_event_type::EVENT_NOTARIZED, 0), notarizedheight(0), MoMdepth(0) {} From a45702061677e0ff09ac9e38bf9ab4c8c3144b54 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 10 Aug 2021 10:06:46 -0500 Subject: [PATCH 32/58] Handle event_opreturn --- src/komodo_events.cpp | 21 ++++------ src/komodo_structs.cpp | 18 ++++----- src/komodo_structs.h | 12 ++++-- src/test-komodo/test_events.cpp | 69 +++++++++++++++++++++++++++++++-- 4 files changed, 92 insertions(+), 28 deletions(-) diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index 4d8adf85f38..92f5053976f 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -46,7 +46,7 @@ void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t heig } else if ( strcmp(symbol,coin) == 0 ) { - std::shared_ptr n = std::make_shared(); + std::shared_ptr n = std::make_shared(height); n->blockhash = notarized_hash; n->desttxid = notarized_desttxid; n->notarizedheight = notarizedheight; @@ -69,7 +69,7 @@ void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t heig */ void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]) { - std::shared_ptr p = std::make_shared(); + std::shared_ptr p = std::make_shared(height); p->num = num; memcpy(p->pubkeys, pubkeys, 33 * num); sp->add_event(symbol, height, p); @@ -87,7 +87,7 @@ void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height */ void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num) { - std::shared_ptr f = std::make_shared(); + std::shared_ptr f = std::make_shared(height); if ( num == sizeof(f->prices)/sizeof(*f->prices) ) { f->num = num; @@ -114,18 +114,13 @@ void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t heigh { if ( ASSETCHAINS_SYMBOL[0] != 0 ) { - std::shared_ptr o = std::make_shared(); - // build a storage area - // JMJ TODO: This looks like a bad idea. Evaluate this code to see if a better way can be found (vector of bytes?) - uint8_t *opret = (uint8_t *)calloc(1,sizeof(komodo::event_opreturn) + opretlen + 16); + std::shared_ptr o = std::make_shared(height); o->txid = txid; o->value = value; o->vout = vout; - memcpy(opret, o.get(), sizeof(komodo::event_opreturn)); - memcpy(&opret[sizeof(komodo::event_opreturn)], buf, opretlen); - o->oplen = opretlen + sizeof(komodo_event_opreturn); + for(uint16_t i = 0; i < opretlen; ++i) + o->opret.push_back(buf[i]); sp->add_event(symbol, height, o); - free(opret); if ( sp != 0 ) komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); } @@ -210,7 +205,7 @@ void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t heig { if ( kmdheight > 0 ) // height is advancing { - std::shared_ptr e = std::shared_ptr(); + std::shared_ptr e = std::make_shared(height); e->timestamp = timestamp; e->kheight = kmdheight; sp->add_event(symbol, height, e); @@ -219,7 +214,7 @@ void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t heig } else // rewinding { - std::shared_ptr e = std::shared_ptr(); + std::shared_ptr e = std::make_shared(height); sp->add_event(symbol, height, e); if ( sp != 0 ) komodo_event_rewind(sp,symbol,height); diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 96b5c44914b..742655446ad 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -270,17 +270,17 @@ std::ostream& operator<<(std::ostream& os, const event_kmdheight& in) event_opreturn::event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height) : event(EVENT_OPRETURN, height) { mem_read(this->txid, data, pos, data_len); - mem_read(this->value, data, pos, data_len); mem_read(this->vout, data, pos, data_len); - mem_read(this->oplen, data, pos, data_len); - this->opret = new uint8_t[this->oplen]; - mem_readn(this->opret, this->oplen, data, pos, data_len); + mem_read(this->value, data, pos, data_len); + uint16_t oplen; + mem_read(oplen, data, pos, data_len); + if (oplen < data_len - pos) + for(uint16_t i = 0; i < oplen; ++i) + this->opret.push_back(data[pos++]); } event_opreturn::~event_opreturn() { - if (opret != nullptr) - delete[] opret; } std::ostream& operator<<(std::ostream& os, const event_opreturn& in) @@ -288,10 +288,10 @@ std::ostream& operator<<(std::ostream& os, const event_opreturn& in) const event& e = dynamic_cast(in); os << e << serializable(in.txid) - << serializable(in.value) << serializable(in.vout) - << serializable(in.oplen); - os.write( (const char*)in.opret, in.oplen); + << serializable(in.value) + << serializable(in.opret.size()); + os.write( (const char*)in.opret.data(), in.opret.size()); return os; } diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 7846e4ceeed..011ad204b10 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -117,6 +117,7 @@ std::ostream& operator<<(std::ostream& os, const event& in); struct event_rewind : public event { event_rewind() : event(komodo_event_type::EVENT_REWIND, 0) {} + event_rewind(int16_t ht) : event(EVENT_REWIND, ht) {} event_rewind(uint8_t* data, long &pos, long data_len, int32_t height); }; std::ostream& operator<<(std::ostream& os, const event_rewind& in); @@ -124,6 +125,7 @@ std::ostream& operator<<(std::ostream& os, const event_rewind& in); struct event_notarized : public event { event_notarized() : event(komodo_event_type::EVENT_NOTARIZED, 0), notarizedheight(0), MoMdepth(0) {} + event_notarized(uint16_t ht) : event(EVENT_NOTARIZED, ht), notarizedheight(0), MoMdepth(0) {} event_notarized(uint8_t* data, long &pos, long data_len, int32_t height, bool includeMoM = false); uint256 blockhash; uint256 desttxid; @@ -140,6 +142,7 @@ struct event_pubkeys : public event * Default ctor */ event_pubkeys() : event(EVENT_PUBKEYS, 0), num(0) {} + event_pubkeys(uint16_t ht) : event(EVENT_PUBKEYS, ht), num(0) {} /*** * ctor from data stream * @param data the data stream @@ -155,6 +158,7 @@ std::ostream& operator<<(std::ostream& os, const event_pubkeys& in); struct event_u : public event { event_u() : event(EVENT_U, 0) {} + event_u(uint16_t ht) : event(EVENT_U, ht) {} event_u(uint8_t *data, long &pos, long data_len, int32_t height); uint8_t n; uint8_t nid; @@ -166,6 +170,7 @@ std::ostream& operator<<(std::ostream& os, const event_u& in); struct event_kmdheight : public event { event_kmdheight() : event(EVENT_KMDHEIGHT, 0) {} + event_kmdheight(uint16_t ht) : event(EVENT_KMDHEIGHT, ht) {} event_kmdheight(uint8_t *data, long &pos, long data_len, int32_t height, bool includeTimestamp = false); int32_t kheight = 0; uint32_t timestamp = 0; @@ -175,19 +180,20 @@ std::ostream& operator<<(std::ostream& os, const event_kmdheight& in); struct event_opreturn : public event { event_opreturn() : event(EVENT_OPRETURN, 0) {} + event_opreturn(uint16_t ht) : event(EVENT_OPRETURN, ht) {} event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height); ~event_opreturn(); uint256 txid; - uint64_t value; uint16_t vout; - uint16_t oplen; - uint8_t *opret = nullptr; + uint64_t value; + std::vector opret; }; std::ostream& operator<<(std::ostream& os, const event_opreturn& in); struct event_pricefeed : public event { event_pricefeed() : event(EVENT_PRICEFEED, 0) {} + event_pricefeed(uint16_t ht) : event(EVENT_PRICEFEED, ht) {} event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height); uint8_t num; uint32_t prices[35]; diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index 98cbfe1ee19..ff1318e73a0 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -88,13 +88,13 @@ void write_r_record(std::FILE* fp) // 8 byte ovalue // 2 byte olen // olen bytes of data - char data[65583] = {'R', 1, 0, 0, 0 }; + char data[50] = {'R', 1, 0, 0, 0 }; memset(&data[5], 1, 32); // txid memset(&data[37], 2, 2); // v memset(&data[39], 3, 8); // ovalue - unsigned char olen[2] = {254, 255}; // 65534 + unsigned char olen[2] = {1,0}; // 1 memcpy(&data[47], olen, 2); - memset(&data[49], 4, 65534); + memset(&data[49], 4, 1); std::fwrite(data, sizeof(data), 1, fp); } void write_v_record(std::FILE* fp) @@ -108,6 +108,11 @@ void write_v_record(std::FILE* fp) memset(&data[6], 1, 140); // data std::fwrite(data, sizeof(data), 1, fp); } +void write_b_record(std::FILE* fp) +{ + char data[] = {'B', 1, 0, 0, 0}; + std::fwrite(data, sizeof(data), 1, fp); +} template bool compare_serialization(const std::string& filename, std::shared_ptr in) { @@ -181,11 +186,13 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way // The first and second event should be pub keys ASSERT_EQ(state->Komodo_numevents, 1); komodo_event* ev1 = state->Komodo_events[0]; ASSERT_EQ(ev1->height, 1); ASSERT_EQ(ev1->type, 'P'); + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 1); std::shared_ptr ev2 = std::dynamic_pointer_cast(state->events.front()); @@ -214,10 +221,12 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way ASSERT_EQ(state->Komodo_numevents, 2); komodo_event* ev = state->Komodo_events[1]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'N'); + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 2); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(++state->events.begin()) ); @@ -246,10 +255,12 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way ASSERT_EQ(state->Komodo_numevents, 3); komodo_event* ev = state->Komodo_events[2]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'N'); // code converts "M" to "N" + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 3); auto itr = state->events.begin(); @@ -280,7 +291,9 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way ASSERT_EQ(state->Komodo_numevents, 3); // does not get added to state + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 3); auto itr = state->events.begin(); @@ -314,10 +327,12 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way ASSERT_EQ(state->Komodo_numevents, 4); komodo_event* ev = state->Komodo_events[3]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'K'); + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 4); auto itr = state->events.begin(); @@ -348,10 +363,12 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way ASSERT_EQ(state->Komodo_numevents, 5); komodo_event* ev = state->Komodo_events[4]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'K'); // changed from T to K + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 5); auto itr = state->events.begin(); @@ -382,10 +399,12 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way ASSERT_EQ(state->Komodo_numevents, 6); komodo_event* ev = state->Komodo_events[5]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'R'); + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 6); auto itr = state->events.begin(); @@ -416,10 +435,12 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* old way ASSERT_EQ(state->Komodo_numevents, 7); komodo_event* ev = state->Komodo_events[6]; ASSERT_EQ(ev->height, 1); ASSERT_EQ(ev->type, 'V'); + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 7); auto itr = state->events.begin(); @@ -430,6 +451,46 @@ TEST(TestEvents, komodo_faststateinit_test) // the serialized version should match the input ASSERT_TRUE(compare_serialization(full_filename, ev2)); } + // record type B (rewind) + { + const std::string temp_filename = temp.native() + "/kmdtypeb.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + ASSERT_NE(fp, nullptr); + write_b_record(fp); + std::fclose(fp); + // verify file still exists + ASSERT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + char symbol[] = "TST"; + komodo_state* state = komodo_stateptrget((char*)symbol); + ASSERT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + // NOTE: B records are not read in. Unsure if this is on purpose or an oversight + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + ASSERT_EQ(result, 1); + /* old way + ASSERT_EQ(state->Komodo_numevents, 7); + komodo_event* ev = state->Komodo_events[6]; + ASSERT_EQ(ev->height, 1); + ASSERT_EQ(ev->type, 'B'); + */ + // check that the new way is the same + ASSERT_EQ(state->events.size(), 7); + /* + auto itr = state->events.begin(); + std::advance(itr, 6); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + ASSERT_NE(ev2, nullptr); + ASSERT_EQ(ev2->height, 1); + ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_REWIND); + // the serialized version should match the input + ASSERT_TRUE(compare_serialization(full_filename, ev2)); + */ + } // all together in 1 file { const std::string temp_filename = temp.native() + "/combined_state.tmp"; @@ -455,10 +516,12 @@ TEST(TestEvents, komodo_faststateinit_test) int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); // compare results ASSERT_EQ(result, 1); + /* ol d way ASSERT_EQ(state->Komodo_numevents, 14); komodo_event* ev1 = state->Komodo_events[7]; ASSERT_EQ(ev1->height, 1); ASSERT_EQ(ev1->type, 'P'); + */ // check that the new way is the same ASSERT_EQ(state->events.size(), 14); auto itr = state->events.begin(); From ac60c674d9229126bb3f857d07106667e4bbd65f Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 10 Aug 2021 12:36:31 -0500 Subject: [PATCH 33/58] ctor to deserialize --- src/komodo.cpp | 107 +++++++++++++++++++++++++++++++++++++----- src/komodo_events.cpp | 99 +++++++++++++++++++++++++------------- src/komodo_events.h | 17 +++++-- 3 files changed, 174 insertions(+), 49 deletions(-) diff --git a/src/komodo.cpp b/src/komodo.cpp index bb4e301bf74..6ac78dccb72 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -185,7 +185,10 @@ int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datal int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) { static int32_t errs; - int32_t func= -1,ht,notarized_height,MoMdepth,num,matched=0; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; long fpos = *fposp; + int32_t func= -1,ht,notarized_height,MoMdepth,num,matched=0; + uint256 MoM,notarized_hash,notarized_desttxid; + uint8_t pubkeys[64][33]; + long fpos = *fposp; if ( fpos < datalen ) { func = filedata[fpos++]; @@ -196,6 +199,8 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long errs++; if ( func == 'P' ) { + // old way: + /* if ( (num= filedata[fpos++]) <= 64 ) { if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) @@ -207,9 +212,28 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); } } else printf("illegal num.%d\n",num); + */ + // new way + try + { + std::shared_ptr pk = std::make_shared(filedata, fpos, datalen, ht); + if (sp != nullptr) + { + if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) + { + komodo_eventadd_pubkeys(sp, symbol, ht, pk); + } + } + } + catch( const komodo::parse_error& pe) + { + errs++; + printf("Unable to parse event_pubkeys: %s\n", pe.what()); + } } else if ( func == 'N' || func == 'M' ) { + /* old way: if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) errs++; if ( memread(¬arized_hash,sizeof(notarized_hash),filedata,&fpos,datalen) != sizeof(notarized_hash) ) @@ -222,8 +246,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long errs++; if ( memread(&MoMdepth,sizeof(MoMdepth),filedata,&fpos,datalen) != sizeof(MoMdepth) ) errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } else { @@ -231,9 +253,22 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long MoMdepth = 0; } komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); + */ + // new way + try + { + std::shared_ptr ntz = + std::make_shared(filedata, fpos, datalen, ht, func == 'M'); + komodo_eventadd_notarized(sp, symbol, ht, ntz); + } + catch( const komodo::parse_error& pe) + { + errs++; + } } else if ( func == 'U' ) // deprecated { + /* old way: uint8_t n,nid; uint256 hash; uint64_t mask; n = filedata[fpos++]; nid = filedata[fpos++]; @@ -242,27 +277,53 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long errs++; if ( memread(&hash,sizeof(hash),filedata,&fpos,datalen) != sizeof(hash) ) errs++; + */ + // new way + try + { + std::shared_ptr u = + std::make_shared(filedata, fpos, datalen, ht); + } + catch( const komodo::parse_error& pe) + { + errs++; + } } - else if ( func == 'K' ) + else if ( func == 'K' || func == 'T' ) { + /* old way: int32_t kheight; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); + */ + // new way: + try + { + std::shared_ptr kmd_ht = + std::make_shared(filedata, fpos, datalen, ht, func == 'T'); + komodo_eventadd_kmdheight(sp, symbol, ht, kmd_ht); + } + catch( const komodo::parse_error& pe) + { + errs++; + } } else if ( func == 'T' ) { + /* old way: int32_t kheight,ktimestamp; if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) errs++; if ( memread(&ktimestamp,sizeof(ktimestamp),filedata,&fpos,datalen) != sizeof(ktimestamp) ) errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); + */ + // new way above } else if ( func == 'R' ) { + /* old way: uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) errs++; @@ -290,6 +351,18 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long filedata[fpos++]; //printf("illegal olen.%u\n",olen); } + */ + // new way + try + { + std::shared_ptr opret = + std::make_shared(filedata, fpos, datalen, ht); + komodo_eventadd_opreturn(sp, symbol, ht, opret); + } + catch( const komodo::parse_error& pe) + { + errs++; + } } else if ( func == 'D' ) { @@ -297,16 +370,28 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'V' ) { + /* old way: int32_t numpvals; uint32_t pvals[128]; numpvals = filedata[fpos++]; if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && memread(pvals,(int32_t)(sizeof(uint32_t)*numpvals),filedata,&fpos,datalen) == numpvals*sizeof(uint32_t) ) { - //if ( matched != 0 ) global shared state -> global PVALS - //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); - //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); - } else printf("error loading pvals[%d]\n",numpvals); - } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); + } + else + printf("error loading pvals[%d]\n",numpvals); + */ + // new way: + try + { + std::shared_ptr pf = + std::make_shared(filedata, fpos, datalen, ht); + komodo_eventadd_pricefeed(sp, symbol, ht, pf); + } + catch( const komodo::parse_error& pe) + { + errs++; + } + } *fposp = fpos; return(func); } diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index 92f5053976f..79cb466f2b0 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -33,29 +33,34 @@ */ void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash, uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) +{ + std::shared_ptr n = std::make_shared(height); + n->blockhash = notarized_hash; + n->desttxid = notarized_desttxid; + n->notarizedheight = notarizedheight; + n->MoM = MoM; + n->MoMdepth = MoMdepth; + strncpy(n->dest, dest, sizeof(n->dest)-1); + komodo_eventadd_notarized(sp, symbol, height, n); +} + +void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr ntz) { char *coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; if ( IS_KOMODO_NOTARY != 0 - && komodo_verifynotarization(symbol,dest,height,notarizedheight,notarized_hash,notarized_desttxid) < 0 ) + && komodo_verifynotarization(symbol,ntz->dest,height,ntz->notarizedheight,ntz->blockhash, ntz->desttxid) < 0 ) { static uint32_t counter; if ( counter++ < 100 ) printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n", - ASSETCHAINS_SYMBOL,height,notarizedheight,dest); + ASSETCHAINS_SYMBOL,height,ntz->notarizedheight, ntz->dest); } else if ( strcmp(symbol,coin) == 0 ) { - std::shared_ptr n = std::make_shared(height); - n->blockhash = notarized_hash; - n->desttxid = notarized_desttxid; - n->notarizedheight = notarizedheight; - n->MoM = MoM; - n->MoMdepth = MoMdepth; - strncpy(n->dest, dest, sizeof(n->dest)-1); - sp->add_event(symbol, height, n); + sp->add_event(symbol, height, ntz); if ( sp != 0 ) - komodo_notarized_update(sp,height,notarizedheight,notarized_hash,notarized_desttxid,MoM,MoMdepth); + komodo_notarized_update(sp,height, ntz->notarizedheight, ntz->blockhash, ntz->desttxid, ntz->MoM, ntz->MoMdepth); } } @@ -72,9 +77,16 @@ void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height std::shared_ptr p = std::make_shared(height); p->num = num; memcpy(p->pubkeys, pubkeys, 33 * num); - sp->add_event(symbol, height, p); - if ( sp != 0 ) - komodo_notarysinit(height,pubkeys,num); + komodo_eventadd_pubkeys(sp, symbol, height, p); +} + +void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pk) +{ + if (sp != nullptr) + { + sp->add_event(symbol, height, pk); + komodo_notarysinit(height, pk->pubkeys, pk->num); + } } /******** @@ -92,9 +104,16 @@ void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t heig { f->num = num; memcpy(f->prices, prices, sizeof(*f->prices) * num); - sp->add_event(symbol, height, f); - if ( sp != 0 ) - komodo_pvals(height,prices,num); + komodo_eventadd_pricefeed( sp, symbol, height, f); + } +} + +void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pf) +{ + if (sp != nullptr) + { + sp->add_event(symbol, height, pf); + komodo_pvals(height,pf->prices, pf->num); } } @@ -120,12 +139,19 @@ void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t heigh o->vout = vout; for(uint16_t i = 0; i < opretlen; ++i) o->opret.push_back(buf[i]); - sp->add_event(symbol, height, o); - if ( sp != 0 ) - komodo_opreturn(height,value,buf,opretlen,txid,vout,symbol); + komodo_eventadd_opreturn(sp, symbol, height, o); } } +void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr opret) +{ + if ( sp != nullptr ) + { + sp->add_event(symbol, height, opret); + komodo_opreturn(height, opret->value, opret->opret.data(), opret->opret.size(), opret->txid, opret->vout, symbol); + } +} + /***** * @brief Undo an event * @note seems to only work for KMD height events @@ -203,20 +229,27 @@ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t time */ void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp) { - if ( kmdheight > 0 ) // height is advancing - { - std::shared_ptr e = std::make_shared(height); - e->timestamp = timestamp; - e->kheight = kmdheight; - sp->add_event(symbol, height, e); - if ( sp != 0 ) - komodo_setkmdheight(sp,kmdheight,timestamp); - } - else // rewinding + std::shared_ptr e = std::make_shared(height); + e->timestamp = timestamp; + e->kheight = kmdheight; + komodo_eventadd_kmdheight(sp, symbol, height, e); +} + +void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height, std::shared_ptr kmdht) +{ + if (sp != nullptr) { - std::shared_ptr e = std::make_shared(height); - sp->add_event(symbol, height, e); - if ( sp != 0 ) + if ( kmdht->kheight > 0 ) // height is advancing + { + + sp->add_event(symbol, height, kmdht); + komodo_setkmdheight(sp, kmdht->kheight, kmdht->timestamp); + } + else // rewinding + { + std::shared_ptr e = std::make_shared(height); + sp->add_event(symbol, height, e); komodo_event_rewind(sp,symbol,height); + } } } diff --git a/src/komodo_events.h b/src/komodo_events.h index 4c4fc354c8a..a13b3ee5393 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -16,18 +16,25 @@ #include "komodo_defs.h" #include "komodo_structs.h" -void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth); +void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height,char *dest, + uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth); +void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr ntz); -void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]); +void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]); +void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pk); void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num); +void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pf); -void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen); +void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout, + uint8_t *buf,uint16_t opretlen); +void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr opret); + +void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp); +void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,std::shared_ptr kmd_ht); void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep); void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp); - -void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp); From 1f3851518290f07b9b017ae90914515da3272707 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 10 Aug 2021 14:15:28 -0500 Subject: [PATCH 34/58] komodo_eventadd replacements --- src/komodo.cpp | 286 ++++++++++------------------------------- src/komodo_events.cpp | 77 +---------- src/komodo_events.h | 9 +- src/komodo_structs.cpp | 68 +++++++++- src/komodo_structs.h | 22 ++-- 5 files changed, 148 insertions(+), 314 deletions(-) diff --git a/src/komodo.cpp b/src/komodo.cpp index 6ac78dccb72..5ffc1f7ad7e 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -51,105 +51,49 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char printf("[%s] matched.%d fpos.%ld func.(%d %c) ht.%d\n",ASSETCHAINS_SYMBOL,matched,ftell(fp),func,func,ht); if ( func == 'P' ) { - if ( (num= fgetc(fp)) <= 64 ) + try { - if ( fread(pubkeys,33,num,fp) != num ) - errs++; - else + std::shared_ptr pk = std::make_shared(fp, ht); + if (sp != nullptr) { - //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); + if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) + { + komodo_eventadd_pubkeys(sp, symbol, ht, pk); + } } - } else printf("illegal num.%d\n",num); - } - else if ( func == 'N' || func == 'M' ) - { - if ( fread(¬arized_height,1,sizeof(notarized_height),fp) != sizeof(notarized_height) ) - errs++; - if ( fread(¬arized_hash,1,sizeof(notarized_hash),fp) != sizeof(notarized_hash) ) - errs++; - if ( fread(¬arized_desttxid,1,sizeof(notarized_desttxid),fp) != sizeof(notarized_desttxid) ) - errs++; - if ( func == 'M' ) - { - if ( fread(&MoM,1,sizeof(MoM),fp) != sizeof(MoM) ) - errs++; - if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && sp != 0 ) - printf("%s load[%s.%d -> %s] NOTARIZED %d %s MoM.%s %d CCid.%u\n",ASSETCHAINS_SYMBOL,symbol,sp->NUM_NPOINTS,dest,notarized_height,notarized_hash.ToString().c_str(),MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff); } - else + catch( const komodo::parse_error& pe) { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; + errs++; + printf("Unable to parse event_pubkeys: %s\n", pe.what()); } - //if ( matched != 0 ) global independent states -> inside *sp - komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); + } + else if ( func == 'N' || func == 'M' ) + { + std::shared_ptr evt = std::make_shared(fp, ht, func == 'M'); + komodo_eventadd_notarized(sp, symbol, ht, evt); } else if ( func == 'U' ) // deprecated { uint8_t n,nid; uint256 hash; uint64_t mask; n = fgetc(fp); nid = fgetc(fp); - //printf("U %d %d\n",n,nid); if ( fread(&mask,1,sizeof(mask),fp) != sizeof(mask) ) errs++; if ( fread(&hash,1,sizeof(hash),fp) != sizeof(hash) ) errs++; - //if ( matched != 0 ) - // komodo_eventadd_utxo(sp,symbol,ht,nid,hash,mask,n); - } - else if ( func == 'K' ) - { - int32_t kheight; - if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) - errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); } - else if ( func == 'T' ) + else if ( func == 'K' || func == 'T') { - int32_t kheight,ktimestamp; - if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) - errs++; - if ( fread(&ktimestamp,1,sizeof(ktimestamp),fp) != sizeof(ktimestamp) ) - errs++; - //if ( matched != 0 ) global independent states -> inside *sp - //printf("%s.%d load[%s] ht.%d t.%u\n",ASSETCHAINS_SYMBOL,ht,symbol,kheight,ktimestamp); - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); + std::shared_ptr evt = std::make_shared(fp, ht, func == 'T'); + komodo_eventadd_kmdheight(sp, symbol, ht, evt); } else if ( func == 'R' ) { - uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; - if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) ) - errs++; - if ( fread(&v,1,sizeof(v),fp) != sizeof(v) ) - errs++; - if ( fread(&ovalue,1,sizeof(ovalue),fp) != sizeof(ovalue) ) - errs++; - if ( fread(&olen,1,sizeof(olen),fp) != sizeof(olen) ) - errs++; - if ( olen < sizeof(opret) ) - { - if ( fread(opret,1,olen,fp) != olen ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) - { - int32_t i; for (i=0; i global PAX - } else - { - int32_t i; - for (i=0; i evt = std::make_shared(fp, ht); + // check for oversized opret + if ( evt->opret.size() < 16384*4 ) + komodo_eventadd_opreturn(sp, symbol, ht, evt); } else if ( func == 'D' ) { @@ -157,16 +101,9 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char } else if ( func == 'V' ) { - int32_t numpvals; uint32_t pvals[128]; - numpvals = fgetc(fp); - if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && fread(pvals,sizeof(uint32_t),numpvals,fp) == numpvals ) - { - //if ( matched != 0 ) global shared state -> global PVALS - //printf("%s load[%s] prices %d\n",ASSETCHAINS_SYMBOL,symbol,ht); - komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); - //printf("load pvals ht.%d numpvals.%d\n",ht,numpvals); - } else printf("error loading pvals[%d]\n",numpvals); - } // else printf("[%s] %s illegal func.(%d %c)\n",ASSETCHAINS_SYMBOL,symbol,func,func); + std::shared_ptr evt = std::make_shared(fp, ht); + komodo_eventadd_pricefeed(sp, symbol, ht, evt); + } return(func); } else return(-1); } @@ -199,21 +136,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long errs++; if ( func == 'P' ) { - // old way: - /* - if ( (num= filedata[fpos++]) <= 64 ) - { - if ( memread(pubkeys,33*num,filedata,&fpos,datalen) != 33*num ) - errs++; - else - { - //printf("updated %d pubkeys at %s ht.%d\n",num,symbol,ht); - if ( (KOMODO_EXTERNAL_NOTARIES != 0 && matched != 0) || (strcmp(symbol,"KMD") == 0 && KOMODO_EXTERNAL_NOTARIES == 0) ) - komodo_eventadd_pubkeys(sp,symbol,ht,num,pubkeys); - } - } else printf("illegal num.%d\n",num); - */ - // new way try { std::shared_ptr pk = std::make_shared(filedata, fpos, datalen, ht); @@ -233,28 +155,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'N' || func == 'M' ) { - /* old way: - if ( memread(¬arized_height,sizeof(notarized_height),filedata,&fpos,datalen) != sizeof(notarized_height) ) - errs++; - if ( memread(¬arized_hash,sizeof(notarized_hash),filedata,&fpos,datalen) != sizeof(notarized_hash) ) - errs++; - if ( memread(¬arized_desttxid,sizeof(notarized_desttxid),filedata,&fpos,datalen) != sizeof(notarized_desttxid) ) - errs++; - if ( func == 'M' ) - { - if ( memread(&MoM,sizeof(MoM),filedata,&fpos,datalen) != sizeof(MoM) ) - errs++; - if ( memread(&MoMdepth,sizeof(MoMdepth),filedata,&fpos,datalen) != sizeof(MoMdepth) ) - errs++; - } - else - { - memset(&MoM,0,sizeof(MoM)); - MoMdepth = 0; - } - komodo_eventadd_notarized(sp,symbol,ht,dest,notarized_hash,notarized_desttxid,notarized_height,MoM,MoMdepth); - */ - // new way try { std::shared_ptr ntz = @@ -268,17 +168,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'U' ) // deprecated { - /* old way: - uint8_t n,nid; uint256 hash; uint64_t mask; - n = filedata[fpos++]; - nid = filedata[fpos++]; - //printf("U %d %d\n",n,nid); - if ( memread(&mask,sizeof(mask),filedata,&fpos,datalen) != sizeof(mask) ) - errs++; - if ( memread(&hash,sizeof(hash),filedata,&fpos,datalen) != sizeof(hash) ) - errs++; - */ - // new way try { std::shared_ptr u = @@ -291,13 +180,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'K' || func == 'T' ) { - /* old way: - int32_t kheight; - if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) - errs++; - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,0); - */ - // new way: try { std::shared_ptr kmd_ht = @@ -309,50 +191,8 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long errs++; } } - else if ( func == 'T' ) - { - /* old way: - int32_t kheight,ktimestamp; - if ( memread(&kheight,sizeof(kheight),filedata,&fpos,datalen) != sizeof(kheight) ) - errs++; - if ( memread(&ktimestamp,sizeof(ktimestamp),filedata,&fpos,datalen) != sizeof(ktimestamp) ) - errs++; - komodo_eventadd_kmdheight(sp,symbol,ht,kheight,ktimestamp); - */ - // new way above - } else if ( func == 'R' ) { - /* old way: - uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[16384*4]; - if ( memread(&txid,sizeof(txid),filedata,&fpos,datalen) != sizeof(txid) ) - errs++; - if ( memread(&v,sizeof(v),filedata,&fpos,datalen) != sizeof(v) ) - errs++; - if ( memread(&ovalue,sizeof(ovalue),filedata,&fpos,datalen) != sizeof(ovalue) ) - errs++; - if ( memread(&olen,sizeof(olen),filedata,&fpos,datalen) != sizeof(olen) ) - errs++; - if ( olen < sizeof(opret) ) - { - if ( memread(opret,olen,filedata,&fpos,datalen) != olen ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && matched != 0 ) - { - int32_t i; for (i=0; i global PAX - } else - { - int32_t i; - for (i=0; i opret = @@ -370,17 +210,6 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'V' ) { - /* old way: - int32_t numpvals; uint32_t pvals[128]; - numpvals = filedata[fpos++]; - if ( numpvals*sizeof(uint32_t) <= sizeof(pvals) && memread(pvals,(int32_t)(sizeof(uint32_t)*numpvals),filedata,&fpos,datalen) == numpvals*sizeof(uint32_t) ) - { - komodo_eventadd_pricefeed(sp,symbol,ht,pvals,numpvals); - } - else - printf("error loading pvals[%d]\n",numpvals); - */ - // new way: try { std::shared_ptr pf = @@ -398,10 +227,19 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long return(-1); } -void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) +void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries, + uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals, + uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue, + uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) { - static FILE *fp; static int32_t errs,didinit; static uint256 zero; - struct komodo_state *sp; char fname[512],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t retval,ht,func; uint8_t num,pubkeys[64][33]; + static FILE *fp; + static int32_t errs,didinit; + static uint256 zero; + struct komodo_state *sp; + char fname[512],symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; + int32_t retval,ht,func; + uint8_t num,pubkeys[64][33]; + if ( didinit == 0 ) { portable_mutex_init(&KOMODO_KV_mutex); @@ -414,7 +252,6 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar printf("[%s] no komodo_stateptr\n",ASSETCHAINS_SYMBOL); return; } - //printf("[%s] (%s) -> (%s)\n",ASSETCHAINS_SYMBOL,symbol,dest); if ( fp == 0 ) { komodo_statefname(fname,ASSETCHAINS_SYMBOL,(char *)"komodostate"); @@ -433,12 +270,10 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar } if ( height <= 0 ) { - //printf("early return: stateupdate height.%d\n",height); return; } if ( fp != 0 ) // write out funcid, height, other fields, call side effect function { - //printf("fpos.%ld ",ftell(fp)); if ( KMDheight != 0 ) { if ( KMDtimestamp != 0 ) @@ -459,7 +294,10 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) errs++; } - komodo_eventadd_kmdheight(sp,symbol,height,KMDheight,KMDtimestamp); + std::shared_ptr kmd_ht = std::make_shared(height); + kmd_ht->kheight = KMDheight; + kmd_ht->timestamp = KMDtimestamp; + komodo_eventadd_kmdheight(sp,symbol,height,kmd_ht); } else if ( opretbuf != 0 && opretlen > 0 ) { @@ -477,9 +315,13 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar errs++; if ( fwrite(opretbuf,1,olen,fp) != olen ) errs++; -//printf("create ht.%d R opret[%d] sp.%p\n",height,olen,sp); - //komodo_opreturn(height,opretvalue,opretbuf,olen,txhash,vout); - komodo_eventadd_opreturn(sp,symbol,height,txhash,opretvalue,vout,opretbuf,olen); + std::shared_ptr evt = std::make_shared(height); + evt->txid = txhash; + evt->vout = vout; + evt->value = opretvalue; + for(uint16_t i = 0; i < olen; ++i) + evt->opret.push_back(opretbuf[i]); + komodo_eventadd_opreturn(sp,symbol,height,evt); } else if ( notarypubs != 0 && numnotaries > 0 ) { @@ -490,11 +332,13 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar fputc(numnotaries,fp); if ( fwrite(notarypubs,33,numnotaries,fp) != numnotaries ) errs++; - komodo_eventadd_pubkeys(sp,symbol,height,numnotaries,notarypubs); + std::shared_ptr pk = std::make_shared(height); + pk->num = numnotaries; + memcpy(pk->pubkeys, notarypubs, 33 * 64); + komodo_eventadd_pubkeys(sp,symbol,height,pk); } else if ( voutmask != 0 && numvouts > 0 ) { - //printf("ht.%d func U %d %d errs.%d hashsize.%ld\n",height,numvouts,notaryid,errs,sizeof(txhash)); fputc('U',fp); if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) errs++; @@ -504,7 +348,6 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar errs++; if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) errs++; - //komodo_eventadd_utxo(sp,symbol,height,notaryid,txhash,voutmask,numvouts); } else if ( pvals != 0 && numpvals > 0 ) { @@ -520,14 +363,15 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar fputc(numpvals,fp); if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals ) errs++; - komodo_eventadd_pricefeed(sp,symbol,height,pvals,numpvals); - //printf("ht.%d V numpvals[%d]\n",height,numpvals); + std::shared_ptr evt = std::make_shared(height); + evt->num = numpvals; + for( uint8_t i = 0; i < evt->num; ++i) + evt->prices[i] = pvals[i]; + komodo_eventadd_pricefeed(sp,symbol,height,evt); } - //printf("save pvals height.%d numpvals.%d\n",height,numpvals); } else if ( height != 0 ) { - //printf("ht.%d func N ht.%d errs.%d\n",height,NOTARIZED_HEIGHT,errs); if ( sp != 0 ) { if ( sp->MoMdepth != 0 && sp->MoM != zero ) @@ -548,7 +392,14 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar if ( fwrite(&sp->MoMdepth,1,sizeof(sp->MoMdepth),fp) != sizeof(sp->MoMdepth) ) errs++; } - komodo_eventadd_notarized(sp,symbol,height,dest,sp->NOTARIZED_HASH,sp->NOTARIZED_DESTTXID,sp->NOTARIZED_HEIGHT,sp->MoM,sp->MoMdepth); + std::shared_ptr evt = std::make_shared(height); + memcpy(evt->dest, dest, 65); + evt->blockhash = sp->NOTARIZED_HASH; + evt->desttxid = sp->NOTARIZED_DESTTXID; + evt->notarizedheight = sp->NOTARIZED_HEIGHT; + evt->MoM = sp->MoM; + evt->MoMdepth = sp->MoMdepth; + komodo_eventadd_notarized(sp,symbol,height,evt); } } fflush(fp); @@ -820,13 +671,6 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar return(notaryid); } -/*int32_t komodo_isratify(int32_t isspecial,int32_t numvalid) -{ - if ( isspecial != 0 && numvalid >= KOMODO_MINRATIFY ) - return(1); - else return(0); -}*/ - // Special tx have vout[0] -> CRYPTO777 // with more than KOMODO_MINRATIFY pay2pubkey outputs -> ratify // if all outputs to notary -> notary utxo diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index 79cb466f2b0..131efd83c1c 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -24,26 +24,8 @@ * @param sp the state to add to * @param symbol * @param height - * @param dest - * @param notarized_hash - * @param notarized_desttxid - * @param notarizedheight - * @param MoM - * @param MoMdepth + * @param ntz the event */ -void komodo_eventadd_notarized(struct komodo_state *sp,char *symbol,int32_t height,char *dest,uint256 notarized_hash, - uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth) -{ - std::shared_ptr n = std::make_shared(height); - n->blockhash = notarized_hash; - n->desttxid = notarized_desttxid; - n->notarizedheight = notarizedheight; - n->MoM = MoM; - n->MoMdepth = MoMdepth; - strncpy(n->dest, dest, sizeof(n->dest)-1); - komodo_eventadd_notarized(sp, symbol, height, n); -} - void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr ntz) { char *coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; @@ -69,17 +51,8 @@ void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, * @param sp where to add * @param symbol * @param height - * @param num - * @param pubkeys + * @param pk the event */ -void komodo_eventadd_pubkeys(struct komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]) -{ - std::shared_ptr p = std::make_shared(height); - p->num = num; - memcpy(p->pubkeys, pubkeys, 33 * num); - komodo_eventadd_pubkeys(sp, symbol, height, p); -} - void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pk) { if (sp != nullptr) @@ -94,20 +67,8 @@ void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, std * @param sp where to add * @param symbol * @param height - * @param prices - * @param num + * @param pf the event */ -void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num) -{ - std::shared_ptr f = std::make_shared(height); - if ( num == sizeof(f->prices)/sizeof(*f->prices) ) - { - f->num = num; - memcpy(f->prices, prices, sizeof(*f->prices) * num); - komodo_eventadd_pricefeed( sp, symbol, height, f); - } -} - void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pf) { if (sp != nullptr) @@ -122,27 +83,8 @@ void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, * @param sp where to add * @param symbol * @param height - * @param txid - * @param value - * @param vout - * @param buf - * @param opretlen + * @param opret the event */ -void komodo_eventadd_opreturn(struct komodo_state *sp,char *symbol,int32_t height,uint256 txid, - uint64_t value,uint16_t vout,uint8_t *buf,uint16_t opretlen) -{ - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - std::shared_ptr o = std::make_shared(height); - o->txid = txid; - o->value = value; - o->vout = vout; - for(uint16_t i = 0; i < opretlen; ++i) - o->opret.push_back(buf[i]); - komodo_eventadd_opreturn(sp, symbol, height, o); - } -} - void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr opret) { if ( sp != nullptr ) @@ -224,17 +166,8 @@ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t time * @param sp * @param symbol * @param height - * @param kmdheight - * @param timestamp + * @param kmdht the event */ -void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp) -{ - std::shared_ptr e = std::make_shared(height); - e->timestamp = timestamp; - e->kheight = kmdheight; - komodo_eventadd_kmdheight(sp, symbol, height, e); -} - void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height, std::shared_ptr kmdht) { if (sp != nullptr) diff --git a/src/komodo_events.h b/src/komodo_events.h index a13b3ee5393..7b7982cf6d1 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -16,21 +16,14 @@ #include "komodo_defs.h" #include "komodo_structs.h" -void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height,char *dest, - uint256 notarized_hash,uint256 notarized_desttxid,int32_t notarizedheight,uint256 MoM,int32_t MoMdepth); void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr ntz); -void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height,uint8_t num,uint8_t pubkeys[64][33]); void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pk); -void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height,uint32_t *prices,uint8_t num); -void komodo_eventadd_pricefeed(struct komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pf); +void komodo_eventadd_pricefeed(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pf); -void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height,uint256 txid,uint64_t value,uint16_t vout, - uint8_t *buf,uint16_t opretlen); void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr opret); -void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,int32_t kmdheight,uint32_t timestamp); void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,std::shared_ptr kmd_ht); void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep); diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 742655446ad..4a289d24813 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -185,6 +185,13 @@ event_pubkeys::event_pubkeys(uint8_t* data, long& pos, long data_len, int32_t he mem_nread(pubkeys, num, data, pos, data_len); } +event_pubkeys::event_pubkeys(FILE* fp, int32_t height) : event(EVENT_PUBKEYS, height) +{ + num = fgetc(fp); + if ( fread(pubkeys,33,num,fp) != num ) + throw parse_error("Illegal number of keys: " + std::to_string(num)); +} + std::ostream& operator<<(std::ostream& os, const event_pubkeys& in) { const event& e = dynamic_cast(in); @@ -218,6 +225,23 @@ event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_ } } +event_notarized::event_notarized(FILE* fp, int32_t height, bool includeMoM) : event(EVENT_NOTARIZED, height) +{ + if ( fread(¬arizedheight,1,sizeof(notarizedheight),fp) != sizeof(notarizedheight) ) + throw parse_error("Invalid notarization height"); + if ( fread(&blockhash,1,sizeof(blockhash),fp) != sizeof(blockhash) ) + throw parse_error("Invalid block hash"); + if ( fread(&desttxid,1,sizeof(desttxid),fp) != sizeof(desttxid) ) + throw parse_error("Invalid Destination TXID"); + if ( includeMoM ) + { + if ( fread(&MoM,1,sizeof(MoM),fp) != sizeof(MoM) ) + throw parse_error("Invalid MoM"); + if ( fread(&MoMdepth,1,sizeof(MoMdepth),fp) != sizeof(MoMdepth) ) + throw parse_error("Invalid MoMdepth"); + } +} + std::ostream& operator<<(std::ostream& os, const event_notarized& in) { const event& e = dynamic_cast(in); @@ -258,6 +282,17 @@ event_kmdheight::event_kmdheight(uint8_t* data, long &pos, long data_len, int32_ mem_read(this->timestamp, data, pos, data_len); } +event_kmdheight::event_kmdheight(FILE *fp, int32_t height, bool includeTimestamp) : event(EVENT_KMDHEIGHT, height) +{ + if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) ) + throw parse_error("Unable to parse KMD height"); + if (includeTimestamp) + { + if ( fread( ×tamp, 1, sizeof(timestamp), fp) != sizeof(timestamp) ) + throw parse_error("Unable to parse timestamp of KMD height"); + } +} + std::ostream& operator<<(std::ostream& os, const event_kmdheight& in) { const event& e = dynamic_cast(in); @@ -274,13 +309,31 @@ event_opreturn::event_opreturn(uint8_t *data, long &pos, long data_len, int32_t mem_read(this->value, data, pos, data_len); uint16_t oplen; mem_read(oplen, data, pos, data_len); - if (oplen < data_len - pos) - for(uint16_t i = 0; i < oplen; ++i) - this->opret.push_back(data[pos++]); + if (oplen <= data_len - pos) + { + this->opret = std::vector( &data[pos], &data[pos] + oplen); + pos += oplen; + } } -event_opreturn::~event_opreturn() +event_opreturn::event_opreturn(FILE* fp, int32_t height) : event(EVENT_OPRETURN, height) { + if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) ) + throw parse_error("Unable to parse txid of opreturn record"); + if ( fread(&vout,1,sizeof(vout),fp) != sizeof(vout) ) + throw parse_error("Unable to parse vout of opreturn record"); + if ( fread(&value,1,sizeof(value),fp) != sizeof(value) ) + throw parse_error("Unable to parse value of opreturn record"); + uint16_t oplen; + if ( fread(&oplen,1,sizeof(oplen),fp) != sizeof(oplen) ) + throw parse_error("Unable to parse length of opreturn record"); + uint8_t *b = new uint8_t[oplen]; + size_t result = fread(b, 1, oplen, fp); + if (result == oplen) + this->opret = std::vector( b, b + oplen); + delete b; + if (result != oplen) + throw parse_error("Unable to parse binary data of opreturn"); } std::ostream& operator<<(std::ostream& os, const event_opreturn& in) @@ -306,6 +359,13 @@ event_pricefeed::event_pricefeed(uint8_t *data, long &pos, long data_len, int32_ pos += num * sizeof(uint32_t); } +event_pricefeed::event_pricefeed(FILE* fp, int32_t height) : event(EVENT_PRICEFEED, height) +{ + num = fgetc(fp); + if ( num * sizeof(uint32_t) <= sizeof(prices) && fread(prices,sizeof(uint32_t),num,fp) != num ) + throw parse_error("Unable to parse price feed"); +} + std::ostream& operator<<(std::ostream& os, const event_pricefeed& in) { const event& e = dynamic_cast(in); diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 011ad204b10..24b5523b9f8 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -117,7 +117,7 @@ std::ostream& operator<<(std::ostream& os, const event& in); struct event_rewind : public event { event_rewind() : event(komodo_event_type::EVENT_REWIND, 0) {} - event_rewind(int16_t ht) : event(EVENT_REWIND, ht) {} + event_rewind(int32_t ht) : event(EVENT_REWIND, ht) {} event_rewind(uint8_t* data, long &pos, long data_len, int32_t height); }; std::ostream& operator<<(std::ostream& os, const event_rewind& in); @@ -125,8 +125,9 @@ std::ostream& operator<<(std::ostream& os, const event_rewind& in); struct event_notarized : public event { event_notarized() : event(komodo_event_type::EVENT_NOTARIZED, 0), notarizedheight(0), MoMdepth(0) {} - event_notarized(uint16_t ht) : event(EVENT_NOTARIZED, ht), notarizedheight(0), MoMdepth(0) {} + event_notarized(int32_t ht) : event(EVENT_NOTARIZED, ht), notarizedheight(0), MoMdepth(0) {} event_notarized(uint8_t* data, long &pos, long data_len, int32_t height, bool includeMoM = false); + event_notarized(FILE* fp, int32_t ht, bool includeMoM = false); uint256 blockhash; uint256 desttxid; uint256 MoM; @@ -142,7 +143,7 @@ struct event_pubkeys : public event * Default ctor */ event_pubkeys() : event(EVENT_PUBKEYS, 0), num(0) {} - event_pubkeys(uint16_t ht) : event(EVENT_PUBKEYS, ht), num(0) {} + event_pubkeys(int32_t ht) : event(EVENT_PUBKEYS, ht), num(0) {} /*** * ctor from data stream * @param data the data stream @@ -150,6 +151,7 @@ struct event_pubkeys : public event * @param data_len full length of data */ event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); + event_pubkeys(FILE* fp, int32_t height); uint8_t num; uint8_t pubkeys[64][33]; }; @@ -158,7 +160,7 @@ std::ostream& operator<<(std::ostream& os, const event_pubkeys& in); struct event_u : public event { event_u() : event(EVENT_U, 0) {} - event_u(uint16_t ht) : event(EVENT_U, ht) {} + event_u(int32_t ht) : event(EVENT_U, ht) {} event_u(uint8_t *data, long &pos, long data_len, int32_t height); uint8_t n; uint8_t nid; @@ -170,8 +172,9 @@ std::ostream& operator<<(std::ostream& os, const event_u& in); struct event_kmdheight : public event { event_kmdheight() : event(EVENT_KMDHEIGHT, 0) {} - event_kmdheight(uint16_t ht) : event(EVENT_KMDHEIGHT, ht) {} + event_kmdheight(int32_t ht) : event(EVENT_KMDHEIGHT, ht) {} event_kmdheight(uint8_t *data, long &pos, long data_len, int32_t height, bool includeTimestamp = false); + event_kmdheight(FILE* fp, int32_t height, bool includeTimestamp = false); int32_t kheight = 0; uint32_t timestamp = 0; }; @@ -180,9 +183,9 @@ std::ostream& operator<<(std::ostream& os, const event_kmdheight& in); struct event_opreturn : public event { event_opreturn() : event(EVENT_OPRETURN, 0) {} - event_opreturn(uint16_t ht) : event(EVENT_OPRETURN, ht) {} + event_opreturn(int32_t ht) : event(EVENT_OPRETURN, ht) {} event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height); - ~event_opreturn(); + event_opreturn(FILE* fp, int32_t height); uint256 txid; uint16_t vout; uint64_t value; @@ -193,8 +196,9 @@ std::ostream& operator<<(std::ostream& os, const event_opreturn& in); struct event_pricefeed : public event { event_pricefeed() : event(EVENT_PRICEFEED, 0) {} - event_pricefeed(uint16_t ht) : event(EVENT_PRICEFEED, ht) {} - event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height); + event_pricefeed(int32_t ht) : event(EVENT_PRICEFEED, ht) {} + event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height); + event_pricefeed(FILE* fp, int32_t height); uint8_t num; uint32_t prices[35]; }; From b1429ce6cdbf1479bb838fae0754f9f44b20a275 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 10 Aug 2021 14:41:45 -0500 Subject: [PATCH 35/58] serialize events --- src/komodo.cpp | 93 +++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 73 deletions(-) diff --git a/src/komodo.cpp b/src/komodo.cpp index 5ffc1f7ad7e..3377f6f81f4 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -227,6 +227,14 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long return(-1); } +size_t write_event(std::shared_ptr evt, FILE *fp) +{ + std::stringstream ss; + ss << evt; + std::string buf = ss.str(); + return fwrite(buf.c_str(), buf.size(), 1, fp); +} + void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries, uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals, uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue, @@ -276,78 +284,39 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar { if ( KMDheight != 0 ) { - if ( KMDtimestamp != 0 ) - { - fputc('T',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) - errs++; - if ( fwrite(&KMDtimestamp,1,sizeof(KMDtimestamp),fp) != sizeof(KMDtimestamp) ) - errs++; - } - else - { - fputc('K',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) ) - errs++; - } std::shared_ptr kmd_ht = std::make_shared(height); kmd_ht->kheight = KMDheight; kmd_ht->timestamp = KMDtimestamp; + write_event(kmd_ht, fp); komodo_eventadd_kmdheight(sp,symbol,height,kmd_ht); } else if ( opretbuf != 0 && opretlen > 0 ) { - uint16_t olen = opretlen; - fputc('R',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) - errs++; - if ( fwrite(&vout,1,sizeof(vout),fp) != sizeof(vout) ) - errs++; - if ( fwrite(&opretvalue,1,sizeof(opretvalue),fp) != sizeof(opretvalue) ) - errs++; - if ( fwrite(&olen,1,sizeof(olen),fp) != olen ) - errs++; - if ( fwrite(opretbuf,1,olen,fp) != olen ) - errs++; std::shared_ptr evt = std::make_shared(height); evt->txid = txhash; evt->vout = vout; evt->value = opretvalue; - for(uint16_t i = 0; i < olen; ++i) + for(uint16_t i = 0; i < opretlen; ++i) evt->opret.push_back(opretbuf[i]); + write_event(evt, fp); komodo_eventadd_opreturn(sp,symbol,height,evt); } else if ( notarypubs != 0 && numnotaries > 0 ) { - printf("ht.%d func P[%d] errs.%d\n",height,numnotaries,errs); - fputc('P',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numnotaries,fp); - if ( fwrite(notarypubs,33,numnotaries,fp) != numnotaries ) - errs++; std::shared_ptr pk = std::make_shared(height); pk->num = numnotaries; memcpy(pk->pubkeys, notarypubs, 33 * 64); + write_event(pk, fp); komodo_eventadd_pubkeys(sp,symbol,height,pk); } else if ( voutmask != 0 && numvouts > 0 ) { - fputc('U',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numvouts,fp); - fputc(notaryid,fp); - if ( fwrite(&voutmask,1,sizeof(voutmask),fp) != sizeof(voutmask) ) - errs++; - if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) ) - errs++; + std::shared_ptr evt = std::make_shared(height); + evt->n = numvouts; + evt->nid = notaryid; + memcpy(evt->mask, &voutmask, sizeof(voutmask)); + memcpy(evt->hash, &txhash, sizeof(txhash)); + write_event(evt, fp); } else if ( pvals != 0 && numpvals > 0 ) { @@ -357,16 +326,11 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar nonz++; if ( nonz >= 32 ) { - fputc('V',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - fputc(numpvals,fp); - if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals ) - errs++; std::shared_ptr evt = std::make_shared(height); evt->num = numpvals; for( uint8_t i = 0; i < evt->num; ++i) evt->prices[i] = pvals[i]; + write_event(evt, fp); komodo_eventadd_pricefeed(sp,symbol,height,evt); } } @@ -374,24 +338,6 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar { if ( sp != 0 ) { - if ( sp->MoMdepth != 0 && sp->MoM != zero ) - fputc('M',fp); - else fputc('N',fp); - if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) ) - errs++; - if ( fwrite(&sp->NOTARIZED_HEIGHT,1,sizeof(sp->NOTARIZED_HEIGHT),fp) != sizeof(sp->NOTARIZED_HEIGHT) ) - errs++; - if ( fwrite(&sp->NOTARIZED_HASH,1,sizeof(sp->NOTARIZED_HASH),fp) != sizeof(sp->NOTARIZED_HASH) ) - errs++; - if ( fwrite(&sp->NOTARIZED_DESTTXID,1,sizeof(sp->NOTARIZED_DESTTXID),fp) != sizeof(sp->NOTARIZED_DESTTXID) ) - errs++; - if ( sp->MoMdepth != 0 && sp->MoM != zero ) - { - if ( fwrite(&sp->MoM,1,sizeof(sp->MoM),fp) != sizeof(sp->MoM) ) - errs++; - if ( fwrite(&sp->MoMdepth,1,sizeof(sp->MoMdepth),fp) != sizeof(sp->MoMdepth) ) - errs++; - } std::shared_ptr evt = std::make_shared(height); memcpy(evt->dest, dest, 65); evt->blockhash = sp->NOTARIZED_HASH; @@ -399,6 +345,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar evt->notarizedheight = sp->NOTARIZED_HEIGHT; evt->MoM = sp->MoM; evt->MoMdepth = sp->MoMdepth; + write_event(evt, fp); komodo_eventadd_notarized(sp,symbol,height,evt); } } From a9878261460bb6590cd394e8451eb5908d5c923c Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 11 Aug 2021 08:28:40 -0500 Subject: [PATCH 36/58] remove memread, clean try/catch --- src/komodo.cpp | 266 +++++++++++++++++------------------------ src/komodo.h | 2 - src/komodo_events.cpp | 24 ++-- src/komodo_structs.cpp | 103 ++++++---------- src/komodo_structs.h | 55 ++++++--- src/mem_read.h | 65 ++++++++++ 6 files changed, 266 insertions(+), 249 deletions(-) create mode 100644 src/mem_read.h diff --git a/src/komodo.cpp b/src/komodo.cpp index cb776d6b841..d8e19cc1a67 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -15,6 +15,7 @@ #include "komodo.h" #include "komodo_extern_globals.h" #include "komodo_notary.h" +#include "mem_read.h" void komodo_currentheight_set(int32_t height) { @@ -23,7 +24,8 @@ void komodo_currentheight_set(int32_t height) sp->CURRENT_HEIGHT = height; } -extern struct NSPV_inforesp NSPV_inforesult; +extern NSPV_inforesp NSPV_inforesult; + int32_t komodo_currentheight() { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; @@ -38,195 +40,147 @@ int32_t komodo_currentheight() int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest) { - static int32_t errs; - int32_t func,ht,notarized_height,num,matched=0,MoMdepth; uint256 MoM,notarized_hash,notarized_desttxid; uint8_t pubkeys[64][33]; - if ( (func= fgetc(fp)) != EOF ) + int32_t func; + + try { - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - matched = 1; - else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) ) - errs++; - if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 && func != 'T' ) - printf("[%s] matched.%d fpos.%ld func.(%d %c) ht.%d\n",ASSETCHAINS_SYMBOL,matched,ftell(fp),func,func,ht); - if ( func == 'P' ) + if ( (func= fgetc(fp)) != EOF ) { - try + bool matched = false; + if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + matched = true; + else + matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + + int32_t ht; + if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) ) + throw komodo::parse_error("Unable to read height from file"); + if ( func == 'P' ) { std::shared_ptr pk = std::make_shared(fp, ht); - if (sp != nullptr) + if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) { - if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) - { - komodo_eventadd_pubkeys(sp, symbol, ht, pk); - } + komodo_eventadd_pubkeys(sp, symbol, ht, pk); } } - catch( const komodo::parse_error& pe) + else if ( func == 'N' || func == 'M' ) { - errs++; - printf("Unable to parse event_pubkeys: %s\n", pe.what()); + std::shared_ptr evt = std::make_shared(fp, ht, func == 'M'); + komodo_eventadd_notarized(sp, symbol, ht, evt); } - } - else if ( func == 'N' || func == 'M' ) - { - std::shared_ptr evt = std::make_shared(fp, ht, func == 'M'); - komodo_eventadd_notarized(sp, symbol, ht, evt); - } - else if ( func == 'U' ) // deprecated - { - uint8_t n,nid; uint256 hash; uint64_t mask; - n = fgetc(fp); - nid = fgetc(fp); - if ( fread(&mask,1,sizeof(mask),fp) != sizeof(mask) ) - errs++; - if ( fread(&hash,1,sizeof(hash),fp) != sizeof(hash) ) - errs++; - } - else if ( func == 'K' || func == 'T') - { - std::shared_ptr evt = std::make_shared(fp, ht, func == 'T'); - komodo_eventadd_kmdheight(sp, symbol, ht, evt); - } - else if ( func == 'R' ) - { - std::shared_ptr evt = std::make_shared(fp, ht); - // check for oversized opret - if ( evt->opret.size() < 16384*4 ) - komodo_eventadd_opreturn(sp, symbol, ht, evt); - } - else if ( func == 'D' ) - { - printf("unexpected function D[%d]\n",ht); - } - else if ( func == 'V' ) - { - std::shared_ptr evt = std::make_shared(fp, ht); - komodo_eventadd_pricefeed(sp, symbol, ht, evt); - } - return(func); - } else return(-1); -} - -int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen) -{ - if ( *fposp+size <= datalen ) + else if ( func == 'U' ) // deprecated + { + std::shared_ptr evt = std::make_shared(fp, ht); + } + else if ( func == 'K' || func == 'T') + { + std::shared_ptr evt = std::make_shared(fp, ht, func == 'T'); + komodo_eventadd_kmdheight(sp, symbol, ht, evt); + } + else if ( func == 'R' ) + { + std::shared_ptr evt = std::make_shared(fp, ht); + // check for oversized opret + if ( evt->opret.size() < 16384*4 ) + komodo_eventadd_opreturn(sp, symbol, ht, evt); + } + else if ( func == 'D' ) + { + printf("unexpected function D[%d]\n",ht); + } + else if ( func == 'V' ) + { + std::shared_ptr evt = std::make_shared(fp, ht); + komodo_eventadd_pricefeed(sp, symbol, ht, evt); + } + } // retrieved the func + } + catch(const komodo::parse_error& pe) { - memcpy(dest,&filedata[*fposp],size); - (*fposp) += size; - return(size); + LogPrintf("Error occurred in parsestatefile: %s\n", pe.what()); + func = -1; } - return(-1); + return func; } int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest) { - static int32_t errs; - int32_t func= -1,ht,notarized_height,MoMdepth,num,matched=0; - uint256 MoM,notarized_hash,notarized_desttxid; - uint8_t pubkeys[64][33]; - long fpos = *fposp; - if ( fpos < datalen ) + int32_t func = -1; + + try { - func = filedata[fpos++]; - if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) - matched = 1; - else matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); - if ( memread(&ht,sizeof(ht),filedata,&fpos,datalen) != sizeof(ht) ) - errs++; - if ( func == 'P' ) + long fpos = *fposp; + if ( fpos < datalen ) { - try + func = filedata[fpos++]; + + bool matched = false; + if ( ASSETCHAINS_SYMBOL[0] == 0 && strcmp(symbol,"KMD") == 0 ) + matched = true; + else + matched = (strcmp(symbol,ASSETCHAINS_SYMBOL) == 0); + + int32_t ht; + if ( mem_read(ht, filedata, fpos, datalen) != sizeof(ht) ) + throw komodo::parse_error("Unable to parse height from file data"); + if ( func == 'P' ) { std::shared_ptr pk = std::make_shared(filedata, fpos, datalen, ht); - if (sp != nullptr) + if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) { - if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) - { - komodo_eventadd_pubkeys(sp, symbol, ht, pk); - } + komodo_eventadd_pubkeys(sp, symbol, ht, pk); } } - catch( const komodo::parse_error& pe) + else if ( func == 'N' || func == 'M' ) { - errs++; - printf("Unable to parse event_pubkeys: %s\n", pe.what()); + std::shared_ptr ntz = + std::make_shared(filedata, fpos, datalen, ht, func == 'M'); + komodo_eventadd_notarized(sp, symbol, ht, ntz); } - } - else if ( func == 'N' || func == 'M' ) - { - try - { - std::shared_ptr ntz = - std::make_shared(filedata, fpos, datalen, ht, func == 'M'); - komodo_eventadd_notarized(sp, symbol, ht, ntz); - } - catch( const komodo::parse_error& pe) - { - errs++; - } - } - else if ( func == 'U' ) // deprecated - { - try - { - std::shared_ptr u = - std::make_shared(filedata, fpos, datalen, ht); - } - catch( const komodo::parse_error& pe) - { - errs++; - } - } - else if ( func == 'K' || func == 'T' ) - { - try - { + else if ( func == 'U' ) // deprecated + { + std::shared_ptr u = + std::make_shared(filedata, fpos, datalen, ht); + } + else if ( func == 'K' || func == 'T' ) + { std::shared_ptr kmd_ht = - std::make_shared(filedata, fpos, datalen, ht, func == 'T'); + std::make_shared(filedata, fpos, datalen, ht, func == 'T'); komodo_eventadd_kmdheight(sp, symbol, ht, kmd_ht); - } - catch( const komodo::parse_error& pe) - { - errs++; - } - } - else if ( func == 'R' ) - { - try - { + } + else if ( func == 'R' ) + { std::shared_ptr opret = - std::make_shared(filedata, fpos, datalen, ht); + std::make_shared(filedata, fpos, datalen, ht); komodo_eventadd_opreturn(sp, symbol, ht, opret); - } - catch( const komodo::parse_error& pe) - { - errs++; - } - } - else if ( func == 'D' ) - { - printf("unexpected function D[%d]\n",ht); - } - else if ( func == 'V' ) - { - try - { + } + else if ( func == 'D' ) + { + printf("unexpected function D[%d]\n",ht); + } + else if ( func == 'V' ) + { std::shared_ptr pf = - std::make_shared(filedata, fpos, datalen, ht); + std::make_shared(filedata, fpos, datalen, ht); komodo_eventadd_pricefeed(sp, symbol, ht, pf); - } - catch( const komodo::parse_error& pe) - { - errs++; - } + } + *fposp = fpos; } - *fposp = fpos; - return(func); } - return(-1); + catch( const komodo::parse_error& pe) + { + LogPrintf("Unable to parse state file data. Error: %s\n", pe.what()); + func = -1; + } + return func; } +/*** + * @brief persist event to file stream + * @param evt the event + * @param fp the file + * @returns the number of bytes written + */ size_t write_event(std::shared_ptr evt, FILE *fp) { std::stringstream ss; diff --git a/src/komodo.h b/src/komodo.h index 7bb68daeaff..bdf0913933f 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -58,8 +58,6 @@ int32_t komodo_currentheight(); int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest); -int32_t memread(void *dest,int32_t size,uint8_t *filedata,long *fposp,long datalen); - int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long *fposp,long datalen,char *symbol,char *dest); void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index e0507d14ae1..9b071587e3d 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -40,9 +40,11 @@ void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, } else if ( strcmp(symbol,coin) == 0 ) { - sp->add_event(symbol, height, ntz); - if ( sp != 0 ) + if ( sp != nullptr ) + { + sp->add_event(symbol, height, ntz); komodo_notarized_update(sp,height, ntz->notarizedheight, ntz->blockhash, ntz->desttxid, ntz->MoM, ntz->MoMdepth); + } } } @@ -87,11 +89,11 @@ void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, */ void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr opret) { - if ( sp != nullptr ) - { - sp->add_event(symbol, height, opret); - komodo_opreturn(height, opret->value, opret->opret.data(), opret->opret.size(), opret->txid, opret->vout, symbol); - } + if ( sp != nullptr ) + { + sp->add_event(symbol, height, opret); + komodo_opreturn(height, opret->value, opret->opret.data(), opret->opret.size(), opret->txid, opret->vout, symbol); + } } /***** @@ -125,8 +127,8 @@ void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) { - struct komodo_event *ep; - if ( sp != 0 ) + komodo_event *ep = nullptr; + if ( sp != nullptr ) { if ( ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) { @@ -136,7 +138,7 @@ void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) } while ( sp->Komodo_events != 0 && sp->Komodo_numevents > 0 ) { - if ( (ep= sp->Komodo_events[sp->Komodo_numevents-1]) != 0 ) + if ( (ep= sp->Komodo_events[sp->Komodo_numevents-1]) != nullptr ) { if ( ep->height < height ) break; @@ -149,7 +151,7 @@ void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp) { - if ( sp != 0 ) + if ( sp != nullptr ) { if ( kmdheight > sp->SAVEDHEIGHT ) { diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 4a289d24813..d3eb2206616 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -1,4 +1,19 @@ -#include +/****************************************************************************** + * Copyright © 2021 Komodo Core Deveelopers * + * * + * 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. * + * * + ******************************************************************************/ +#include "komodo_structs.h" +#include "mem_read.h" #include extern std::mutex komodo_mutex; @@ -66,63 +81,6 @@ std::ostream& operator<<(std::ostream& os, serializable in) return os; } -/*** - * Read a chunk of memory - */ - -template -std::size_t mem_read(T& dest, uint8_t *filedata, long &fpos, long datalen) -{ - if (fpos + sizeof(T) <= datalen) - { - memcpy( &dest, &filedata[fpos], sizeof(T) ); - fpos += sizeof(T); - return sizeof(T); - } - throw parse_error("Invalid size: " + std::to_string(sizeof(T)) ); -} - -std::size_t mem_readn(void* dest, size_t num_bytes, uint8_t *filedata, long &fpos, long datalen) -{ - if (fpos + num_bytes <= datalen) - { - memcpy(dest, &filedata[fpos], num_bytes ); - fpos += num_bytes; - return num_bytes; - } - throw parse_error("Invalid size: " + std::to_string(num_bytes) ); -} - -template -std::size_t mem_read(T(&dest)[N], uint8_t *filedata, long& fpos, long datalen) -{ - std::size_t sz = sizeof(T) * N; - if (fpos + sz <= datalen) - { - memcpy( &dest, &filedata[fpos], sz ); - fpos += sz; - return sz; - } - throw parse_error("Invalid size: " + std::to_string( sz ) ); -} - -/**** - * Read a size that is less than the array length - */ -template -std::size_t mem_nread(T(&dest)[N], size_t num_elements, uint8_t *filedata, long& fpos, long datalen) -{ - std::size_t sz = sizeof(T) * num_elements; - if (fpos + sz <= datalen) - { - memcpy( &dest, &filedata[fpos], sz ); - fpos += sz; - return sz; - } - throw parse_error("Invalid size: " + std::to_string(sz)); -} - - /**** * This serializes the 5 byte header of an event * @param os the stream @@ -213,8 +171,10 @@ std::ostream& operator<<(std::ostream& os, const event_rewind& in) return os; } -event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, bool includeMoM) : event(EVENT_NOTARIZED, height) +event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, bool includeMoM) + : event(EVENT_NOTARIZED, height), MoMdepth(0) { + MoM.SetNull(); mem_read(this->notarizedheight, data, pos, data_len); mem_read(this->blockhash, data, pos, data_len); mem_read(this->desttxid, data, pos, data_len); @@ -225,8 +185,10 @@ event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_ } } -event_notarized::event_notarized(FILE* fp, int32_t height, bool includeMoM) : event(EVENT_NOTARIZED, height) +event_notarized::event_notarized(FILE* fp, int32_t height, bool includeMoM) + : event(EVENT_NOTARIZED, height), MoMdepth(0) { + MoM.SetNull(); if ( fread(¬arizedheight,1,sizeof(notarizedheight),fp) != sizeof(notarizedheight) ) throw parse_error("Invalid notarization height"); if ( fread(&blockhash,1,sizeof(blockhash),fp) != sizeof(blockhash) ) @@ -265,6 +227,18 @@ event_u::event_u(uint8_t *data, long &pos, long data_len, int32_t height) : even mem_read(this->hash, data, pos, data_len); } +event_u::event_u(FILE *fp, int32_t height) : event(EVENT_U, height) +{ + if (fread(&n, 1, sizeof(n), fp) != sizeof(n)) + throw parse_error("Unable to read n of event U from file"); + if (fread(&nid, 1, sizeof(nid), fp) != sizeof(n)) + throw parse_error("Unable to read nid of event U from file"); + if (fread(&mask, 1, sizeof(mask), fp) != sizeof(mask)) + throw parse_error("Unable to read mask of event U from file"); + if (fread(&hash, 1, sizeof(hash), fp) != sizeof(hash)) + throw parse_error("Unable to read hash of event U from file"); +} + std::ostream& operator<<(std::ostream& os, const event_u& in) { const event& e = dynamic_cast(in); @@ -327,13 +301,10 @@ event_opreturn::event_opreturn(FILE* fp, int32_t height) : event(EVENT_OPRETURN, uint16_t oplen; if ( fread(&oplen,1,sizeof(oplen),fp) != sizeof(oplen) ) throw parse_error("Unable to parse length of opreturn record"); - uint8_t *b = new uint8_t[oplen]; - size_t result = fread(b, 1, oplen, fp); - if (result == oplen) - this->opret = std::vector( b, b + oplen); - delete b; - if (result != oplen) + std::unique_ptr b(new uint8_t[oplen]); + if ( fread(b.get(), 1, oplen, fp) != oplen) throw parse_error("Unable to parse binary data of opreturn"); + this->opret = std::vector( b.get(), b.get() + oplen); } std::ostream& operator<<(std::ostream& os, const event_opreturn& in) diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 0704ddbbd59..a1e801bc6d3 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -135,8 +135,14 @@ struct event_pubkeys : public event /*** * Default ctor */ - event_pubkeys() : event(EVENT_PUBKEYS, 0), num(0) {} - event_pubkeys(int32_t ht) : event(EVENT_PUBKEYS, ht), num(0) {} + event_pubkeys() : event(EVENT_PUBKEYS, 0), num(0) + { + memset(pubkeys, 0, 64 * 33); + } + event_pubkeys(int32_t ht) : event(EVENT_PUBKEYS, ht), num(0) + { + memset(pubkeys, 0, 64 * 33); + } /*** * ctor from data stream * @param data the data stream @@ -145,18 +151,27 @@ struct event_pubkeys : public event */ event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); event_pubkeys(FILE* fp, int32_t height); - uint8_t num; + uint8_t num = 0; uint8_t pubkeys[64][33]; }; std::ostream& operator<<(std::ostream& os, const event_pubkeys& in); struct event_u : public event { - event_u() : event(EVENT_U, 0) {} - event_u(int32_t ht) : event(EVENT_U, ht) {} + event_u() : event(EVENT_U, 0) + { + memset(mask, 0, 8); + memset(hash, 0, 32); + } + event_u(int32_t ht) : event(EVENT_U, ht) + { + memset(mask, 0, 8); + memset(hash, 0, 32); + } event_u(uint8_t *data, long &pos, long data_len, int32_t height); - uint8_t n; - uint8_t nid; + event_u(FILE* fp, int32_t height); + uint8_t n = 0; + uint8_t nid = 0; uint8_t mask[8]; uint8_t hash[32]; }; @@ -175,24 +190,36 @@ std::ostream& operator<<(std::ostream& os, const event_kmdheight& in); struct event_opreturn : public event { - event_opreturn() : event(EVENT_OPRETURN, 0) {} - event_opreturn(int32_t ht) : event(EVENT_OPRETURN, ht) {} + event_opreturn() : event(EVENT_OPRETURN, 0) + { + txid.SetNull(); + } + event_opreturn(int32_t ht) : event(EVENT_OPRETURN, ht) + { + txid.SetNull(); + } event_opreturn(uint8_t *data, long &pos, long data_len, int32_t height); event_opreturn(FILE* fp, int32_t height); uint256 txid; - uint16_t vout; - uint64_t value; + uint16_t vout = 0; + uint64_t value = 0; std::vector opret; }; std::ostream& operator<<(std::ostream& os, const event_opreturn& in); struct event_pricefeed : public event { - event_pricefeed() : event(EVENT_PRICEFEED, 0) {} - event_pricefeed(int32_t ht) : event(EVENT_PRICEFEED, ht) {} + event_pricefeed() : event(EVENT_PRICEFEED, 0), num(0) + { + memset(prices, 0, 35); + } + event_pricefeed(int32_t ht) : event(EVENT_PRICEFEED, ht) + { + memset(prices, 0, 35); + } event_pricefeed(uint8_t *data, long &pos, long data_len, int32_t height); event_pricefeed(FILE* fp, int32_t height); - uint8_t num; + uint8_t num = 0; uint32_t prices[35]; }; std::ostream& operator<<(std::ostream& os, const event_pricefeed& in); diff --git a/src/mem_read.h b/src/mem_read.h new file mode 100644 index 00000000000..be041607c66 --- /dev/null +++ b/src/mem_read.h @@ -0,0 +1,65 @@ +#pragma once +/****************************************************************************** + * Copyright © 2021 Komodo Core Deveelopers * + * * + * 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. * + * * + ******************************************************************************/ + +#include "komodo_structs.h" // for parse_error + +#include +#include + +/*** + * These read a chunk of memory with some built-in type safety + */ + +template +std::size_t mem_read(T& dest, uint8_t *filedata, long &fpos, long datalen) +{ + if (fpos + sizeof(T) <= datalen) + { + memcpy( &dest, &filedata[fpos], sizeof(T) ); + fpos += sizeof(T); + return sizeof(T); + } + throw komodo::parse_error("Invalid size: " + std::to_string(sizeof(T)) ); +} + +template +std::size_t mem_read(T(&dest)[N], uint8_t *filedata, long& fpos, long datalen) +{ + std::size_t sz = sizeof(T) * N; + if (fpos + sz <= datalen) + { + memcpy( &dest, &filedata[fpos], sz ); + fpos += sz; + return sz; + } + throw komodo::parse_error("Invalid size: " + std::to_string( sz ) ); +} + +/**** + * Read a size that is less than the array length + */ +template +std::size_t mem_nread(T(&dest)[N], size_t num_elements, uint8_t *filedata, long& fpos, long datalen) +{ + std::size_t sz = sizeof(T) * num_elements; + if (fpos + sz <= datalen) + { + memcpy( &dest, &filedata[fpos], sz ); + fpos += sz; + return sz; + } + throw komodo::parse_error("Invalid size: " + std::to_string(sz)); +} \ No newline at end of file From 92177b5716dc34b0824d267975bbc9c66224b1e2 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 11 Aug 2021 10:27:49 -0500 Subject: [PATCH 37/58] fix #include for mac --- src/komodo_cutils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/komodo_cutils.cpp b/src/komodo_cutils.cpp index 77541834f60..de734fa72a9 100644 --- a/src/komodo_cutils.cpp +++ b/src/komodo_cutils.cpp @@ -2,6 +2,10 @@ #include "stdlib.h" //malloc #include "hex.h" +#ifdef __APPLE__ +#include // sleep +#endif + int32_t safecopy(char *dest,char *src,long len) { int32_t i = -1; From 04bb028022d524390cd412830c94a0c3a10216da Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 11 Aug 2021 19:15:47 +0300 Subject: [PATCH 38/58] remove dead dns seeders --- src/chainparams.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 95b86adfe3f..ba5cc7e7398 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -182,8 +182,13 @@ class CMainParams : public CChainParams { assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); vFixedSeeds.clear(); vSeeds.clear(); - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); // Static contolled seeds list (Kolo) - vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); // Active seeds crawler (Kolo) + + vSeeds.push_back(CDNSSeedData("kmd.sh", "seeds1.kmd.sh")); + /* + vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); + vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); + */ + // TODO: we need more seed crawlers from other community members base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,60); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); From e14c9cca1b274e29154ceb415b997ae4727cb615 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 11 Aug 2021 19:25:13 +0300 Subject: [PATCH 39/58] added fixed seeds nodes --- contrib/seeds/nodes_main.txt | 10 ++++------ src/chainparamsseeds.h | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt index a6e8be20753..92df0ed8420 100644 --- a/contrib/seeds/nodes_main.txt +++ b/contrib/seeds/nodes_main.txt @@ -1,6 +1,4 @@ -185.25.48.236:27485 -185.25.48.236:27487 -185.64.105.111:27485 -185.64.105.111:27487 -185.25.48.72:27485 -185.25.48.72:27487 +199.127.60.142:7770 +104.238.221.61:7770 +209.222.101.247:7770 +103.195.100.32:7770 diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index e3dac3ca641..f518769fb2d 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -23,12 +23,10 @@ * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487} + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x7f,0x3c,0x8e}, 7770}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0xdd,0x3d}, 7770}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0xde,0x65,0xf7}, 7770}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xc3,0x64,0x20}, 7770} }; static SeedSpec6 pnSeed6_test[] = { From 5e1634c9ba08dcaeb58e807d0e68f459cdaa97f2 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 11 Aug 2021 21:02:38 +0300 Subject: [PATCH 40/58] add cipig's dns seeder --- src/chainparams.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ba5cc7e7398..afdd3ad71fa 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -184,6 +184,8 @@ class CMainParams : public CChainParams { vSeeds.clear(); vSeeds.push_back(CDNSSeedData("kmd.sh", "seeds1.kmd.sh")); + vSeeds.push_back(CDNSSeedData("cipig.net", "kmdseed.cipig.net")); + /* vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); vSeeds.push_back(CDNSSeedData("komodoseeds.com", "dynamic.komodoseeds.com")); From adc18d34ee4ccc8de88fdde3a094b4c0cd53bb7b Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 12 Aug 2021 03:41:59 +0300 Subject: [PATCH 41/58] add komodoseeds.org dns seeder --- src/chainparams.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index afdd3ad71fa..6843ffecdb3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -183,6 +183,7 @@ class CMainParams : public CChainParams { vFixedSeeds.clear(); vSeeds.clear(); + vSeeds.push_back(CDNSSeedData("komodoseeds.org", "kmd.komodoseeds.org")); vSeeds.push_back(CDNSSeedData("kmd.sh", "seeds1.kmd.sh")); vSeeds.push_back(CDNSSeedData("cipig.net", "kmdseed.cipig.net")); From 810d308d0792a560f05937b7989b6868381c1dc8 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 12 Aug 2021 14:17:13 +0300 Subject: [PATCH 42/58] add gcharang's dns seeder --- src/chainparams.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 6843ffecdb3..264bd512dbb 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -183,9 +183,10 @@ class CMainParams : public CChainParams { vFixedSeeds.clear(); vSeeds.clear(); - vSeeds.push_back(CDNSSeedData("komodoseeds.org", "kmd.komodoseeds.org")); - vSeeds.push_back(CDNSSeedData("kmd.sh", "seeds1.kmd.sh")); - vSeeds.push_back(CDNSSeedData("cipig.net", "kmdseed.cipig.net")); + vSeeds.push_back(CDNSSeedData("komodoseeds.org", "kmd.komodoseeds.org")); // decker + vSeeds.push_back(CDNSSeedData("kmd.sh", "seeds1.kmd.sh")); // decker + vSeeds.push_back(CDNSSeedData("cipig.net", "kmdseed.cipig.net")); // cipig + vSeeds.push_back(CDNSSeedData("lordofthechains.com", "kmdseeds.lordofthechains.com")); // gcharang /* vSeeds.push_back(CDNSSeedData("komodoseeds.com", "kmd.komodoseeds.com")); From 61d30df392c61163df3f85b9981b93bcf6573354 Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Fri, 13 Aug 2021 07:56:58 -0500 Subject: [PATCH 43/58] debug build for mac --- zcutil/build-mac.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index ea03242cc71..aa030b8a019 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -42,15 +42,8 @@ PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -#BUILD CCLIB - -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD - ./autogen.sh + CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" From a073efa1ec2fbb9c64ab63b4b7a0c68e28385bda Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 Aug 2021 06:50:49 -0500 Subject: [PATCH 44/58] fix rewind --- src/komodo_events.cpp | 31 ++++++++++++++----------------- src/komodo_events.h | 6 +++--- src/komodo_structs.h | 4 ++-- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index 9b071587e3d..e9c4b68aff1 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -89,7 +89,7 @@ void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, */ void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr opret) { - if ( sp != nullptr ) + if ( sp != nullptr && ASSETCHAINS_SYMBOL[0] != 0) { sp->add_event(symbol, height, opret); komodo_opreturn(height, opret->value, opret->opret.data(), opret->opret.size(), opret->txid, opret->vout, symbol); @@ -100,20 +100,20 @@ void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, s * @brief Undo an event * @note seems to only work for KMD height events * @param sp the state object - * @param ep the event to undo + * @param ev the event to undo */ -void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) +void komodo_event_undo(komodo_state *sp, std::shared_ptr ev) { - switch ( ep->type ) + switch ( ev->type ) { case KOMODO_EVENT_RATIFY: - printf("rewind of ratify, needs to be coded.%d\n",ep->height); + printf("rewind of ratify, needs to be coded.%d\n",ev->height); break; case KOMODO_EVENT_NOTARIZED: break; case KOMODO_EVENT_KMDHEIGHT: - if ( ep->height <= sp->SAVEDHEIGHT ) - sp->SAVEDHEIGHT = ep->height; + if ( ev->height <= sp->SAVEDHEIGHT ) + sp->SAVEDHEIGHT = ev->height; break; case KOMODO_EVENT_PRICEFEED: // backtrack prices; @@ -125,9 +125,8 @@ void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep) } -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) +void komodo_event_rewind(komodo_state *sp, char *symbol, int32_t height) { - komodo_event *ep = nullptr; if ( sp != nullptr ) { if ( ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_LASTMINED && prevKOMODO_LASTMINED != 0 ) @@ -136,15 +135,13 @@ void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height) KOMODO_LASTMINED = prevKOMODO_LASTMINED; prevKOMODO_LASTMINED = 0; } - while ( sp->Komodo_events != 0 && sp->Komodo_numevents > 0 ) + while ( sp->events.size() > 0) { - if ( (ep= sp->Komodo_events[sp->Komodo_numevents-1]) != nullptr ) - { - if ( ep->height < height ) - break; - komodo_event_undo(sp,ep); - sp->Komodo_numevents--; - } + auto ev = sp->events.back(); + if (ev-> height < height) + break; + komodo_event_undo(sp, ev); + sp->events.pop_back(); } } } diff --git a/src/komodo_events.h b/src/komodo_events.h index 7b7982cf6d1..31cd2407dfc 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -26,8 +26,8 @@ void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height, std: void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,std::shared_ptr kmd_ht); -void komodo_event_undo(struct komodo_state *sp,struct komodo_event *ep); +void komodo_event_undo(komodo_state *sp, std::shared_ptr ep); -void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height); +void komodo_event_rewind(komodo_state *sp,char *symbol,int32_t height); -void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t timestamp); +void komodo_setkmdheight(komodo_state *sp,int32_t kmdheight,uint32_t timestamp); diff --git a/src/komodo_structs.h b/src/komodo_structs.h index a1e801bc6d3..ba2055956e8 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -274,8 +274,8 @@ struct komodo_state int32_t SAVEDHEIGHT,CURRENT_HEIGHT,NOTARIZED_HEIGHT,MoMdepth; uint32_t SAVEDTIMESTAMP; uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; - struct notarized_checkpoint *NPOINTS; int32_t NUM_NPOINTS,last_NPOINTSi; - struct komodo_event **Komodo_events; int32_t Komodo_numevents; + struct notarized_checkpoint *NPOINTS; + int32_t NUM_NPOINTS,last_NPOINTSi; std::list> events; uint32_t RTbufs[64][3]; uint64_t RTmask; bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); From 44a796af86b04bd90895b12b464e12f5b9206434 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 Aug 2021 07:39:19 -0500 Subject: [PATCH 45/58] add KMD test --- src/test-komodo/test_events.cpp | 655 +++++++++++++++++++++++++------- 1 file changed, 527 insertions(+), 128 deletions(-) diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index ff1318e73a0..aeed712b586 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -155,7 +155,8 @@ bool compare_serialization(const std::string& filename, std::shared_ptr in) */ TEST(TestEvents, komodo_faststateinit_test) { - strcpy(ASSETCHAINS_SYMBOL, "TST"); + char *symbol = "TST"; + strcpy(ASSETCHAINS_SYMBOL, symbol); KOMODO_EXTERNAL_NOTARIES = 1; boost::filesystem::path temp = boost::filesystem::unique_path(); @@ -172,34 +173,33 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_p_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = nullptr; // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way // The first and second event should be pub keys - ASSERT_EQ(state->Komodo_numevents, 1); + EXPECT_EQ(state->Komodo_numevents, 1); komodo_event* ev1 = state->Komodo_events[0]; - ASSERT_EQ(ev1->height, 1); - ASSERT_EQ(ev1->type, 'P'); + EXPECT_EQ(ev1->height, 1); + EXPECT_EQ(ev1->type, 'P'); */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 1); + EXPECT_EQ(state->events.size(), 1); std::shared_ptr ev2 = std::dynamic_pointer_cast(state->events.front()); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PUBKEYS); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PUBKEYS); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // notarized record { @@ -207,33 +207,32 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_n_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 2); + EXPECT_EQ(state->Komodo_numevents, 2); komodo_event* ev = state->Komodo_events[1]; - ASSERT_EQ(ev->height, 1); - ASSERT_EQ(ev->type, 'N'); + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'N'); */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 2); + EXPECT_EQ(state->events.size(), 2); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(++state->events.begin()) ); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // notarized M record { @@ -241,35 +240,34 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_m_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 3); + EXPECT_EQ(state->Komodo_numevents, 3); komodo_event* ev = state->Komodo_events[2]; - ASSERT_EQ(ev->height, 1); - ASSERT_EQ(ev->type, 'N'); // code converts "M" to "N" + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'N'); // code converts "M" to "N" */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 3); + EXPECT_EQ(state->events.size(), 3); auto itr = state->events.begin(); std::advance(itr, 2); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // record type "U" (deprecated) { @@ -277,25 +275,24 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_u_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 3); // does not get added to state + EXPECT_EQ(state->Komodo_numevents, 3); // does not get added to state */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 3); + EXPECT_EQ(state->events.size(), 3); auto itr = state->events.begin(); // this does not get added to state, so we need to serialize the object just // to verify serialization works as expected @@ -305,7 +302,7 @@ TEST(TestEvents, komodo_faststateinit_test) ev2->nid = 'I'; memset(ev2->mask, 1, 8); memset(ev2->hash, 2, 32); - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // record type K (KMD height) { @@ -313,35 +310,34 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_k_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 4); + EXPECT_EQ(state->Komodo_numevents, 4); komodo_event* ev = state->Komodo_events[3]; - ASSERT_EQ(ev->height, 1); - ASSERT_EQ(ev->type, 'K'); + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'K'); */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 4); + EXPECT_EQ(state->events.size(), 4); auto itr = state->events.begin(); std::advance(itr, 3); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // record type T (KMD height with timestamp) { @@ -349,35 +345,34 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_t_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 5); + EXPECT_EQ(state->Komodo_numevents, 5); komodo_event* ev = state->Komodo_events[4]; - ASSERT_EQ(ev->height, 1); - ASSERT_EQ(ev->type, 'K'); // changed from T to K + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'K'); // changed from T to K */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 5); + EXPECT_EQ(state->events.size(), 5); auto itr = state->events.begin(); std::advance(itr, 4); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // record type R (opreturn) { @@ -385,35 +380,34 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_r_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 6); + EXPECT_EQ(state->Komodo_numevents, 6); komodo_event* ev = state->Komodo_events[5]; - ASSERT_EQ(ev->height, 1); - ASSERT_EQ(ev->type, 'R'); + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'R'); */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 6); + EXPECT_EQ(state->events.size(), 6); auto itr = state->events.begin(); std::advance(itr, 5); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_OPRETURN); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_OPRETURN); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // record type V { @@ -421,35 +415,34 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_v_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 7); + EXPECT_EQ(state->Komodo_numevents, 7); komodo_event* ev = state->Komodo_events[6]; - ASSERT_EQ(ev->height, 1); - ASSERT_EQ(ev->type, 'V'); + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'V'); */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 7); + EXPECT_EQ(state->events.size(), 7); auto itr = state->events.begin(); std::advance(itr, 6); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PRICEFEED); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PRICEFEED); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // record type B (rewind) { @@ -457,38 +450,37 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_b_record(fp); std::fclose(fp); // verify file still exists - ASSERT_TRUE(boost::filesystem::exists(full_filename)); + EXPECT_TRUE(boost::filesystem::exists(full_filename)); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file // NOTE: B records are not read in. Unsure if this is on purpose or an oversight int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* old way - ASSERT_EQ(state->Komodo_numevents, 7); + EXPECT_EQ(state->Komodo_numevents, 7); komodo_event* ev = state->Komodo_events[6]; - ASSERT_EQ(ev->height, 1); - ASSERT_EQ(ev->type, 'B'); + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'B'); */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 7); + EXPECT_EQ(state->events.size(), 7); /* auto itr = state->events.begin(); std::advance(itr, 6); std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - ASSERT_NE(ev2, nullptr); - ASSERT_EQ(ev2->height, 1); - ASSERT_EQ(ev2->type, komodo::komodo_event_type::EVENT_REWIND); + EXPECT_NE(ev2, nullptr); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_REWIND); // the serialized version should match the input - ASSERT_TRUE(compare_serialization(full_filename, ev2)); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); */ } // all together in 1 file @@ -497,7 +489,7 @@ TEST(TestEvents, komodo_faststateinit_test) char full_filename[temp_filename.size()+1]; strcpy(full_filename, temp_filename.c_str()); std::FILE* fp = std::fopen(full_filename, "wb+"); - ASSERT_NE(fp, nullptr); + EXPECT_NE(fp, nullptr); write_p_record(fp); write_n_record(fp); write_m_record(fp); @@ -508,57 +500,464 @@ TEST(TestEvents, komodo_faststateinit_test) write_v_record(fp); std::fclose(fp); // attempt to read the file - char symbol[] = "TST"; komodo_state* state = komodo_stateptrget((char*)symbol); - ASSERT_NE(state, nullptr); + EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); // compare results - ASSERT_EQ(result, 1); + EXPECT_EQ(result, 1); /* ol d way - ASSERT_EQ(state->Komodo_numevents, 14); + EXPECT_EQ(state->Komodo_numevents, 14); komodo_event* ev1 = state->Komodo_events[7]; - ASSERT_EQ(ev1->height, 1); - ASSERT_EQ(ev1->type, 'P'); + EXPECT_EQ(ev1->height, 1); + EXPECT_EQ(ev1->type, 'P'); */ // check that the new way is the same - ASSERT_EQ(state->events.size(), 14); + EXPECT_EQ(state->events.size(), 14); auto itr = state->events.begin(); std::advance(itr, 7); { - ASSERT_EQ( (*itr)->height, 1); - ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PUBKEYS); + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PUBKEYS); itr++; } { - ASSERT_EQ( (*itr)->height, 1); - ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); itr++; } { - ASSERT_EQ( (*itr)->height, 1); - ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); itr++; } { - ASSERT_EQ( (*itr)->height, 1); - ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); itr++; } { - ASSERT_EQ( (*itr)->height, 1); - ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); itr++; } { - ASSERT_EQ( (*itr)->height, 1); - ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_OPRETURN); + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_OPRETURN); itr++; } { - ASSERT_EQ( (*itr)->height, 1); - ASSERT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PRICEFEED); + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PRICEFEED); + itr++; + } + } + } + catch(...) + { + FAIL() << "Exception thrown"; + } + boost::filesystem::remove_all(temp); +} + +TEST(TestEvents, komodo_faststateinit_test_kmd) +{ + char *symbol = "KMD"; + ASSETCHAINS_SYMBOL[0] = 0; + KOMODO_EXTERNAL_NOTARIES = 0; + + boost::filesystem::path temp = boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + try + { + // NOTE: header contains a 5 byte header that is make up of + // an 8 bit identifier (i.e. 'P', 'N', etc.) + // plus a 32 bit height. Everything else is record specific + // pubkey record + { + // create a binary file that should be readable by komodo + const std::string temp_filename = temp.native() + "/kstate.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = nullptr; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + // The first and second event should be pub keys + EXPECT_EQ(state->Komodo_numevents, 1); + komodo_event* ev1 = state->Komodo_events[0]; + EXPECT_EQ(ev1->height, 1); + EXPECT_EQ(ev1->type, 'P'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 1); + std::shared_ptr ev2 = std::dynamic_pointer_cast(state->events.front()); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PUBKEYS); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // notarized record + { + const std::string temp_filename = temp.native() + "/notarized.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_n_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 2); + komodo_event* ev = state->Komodo_events[1]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'N'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 2); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(++state->events.begin()) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // notarized M record + { + const std::string temp_filename = temp.native() + "/notarized.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_m_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 3); + komodo_event* ev = state->Komodo_events[2]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'N'); // code converts "M" to "N" + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 3); + auto itr = state->events.begin(); + std::advance(itr, 2); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type "U" (deprecated) + { + const std::string temp_filename = temp.native() + "/type_u.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_u_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 3); // does not get added to state + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 3); + auto itr = state->events.begin(); + // this does not get added to state, so we need to serialize the object just + // to verify serialization works as expected + std::shared_ptr ev2 = std::make_shared(); + ev2->height = 1; + ev2->n = 'N'; + ev2->nid = 'I'; + memset(ev2->mask, 1, 8); + memset(ev2->hash, 2, 32); + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type K (KMD height) + { + const std::string temp_filename = temp.native() + "/kmdtype.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_k_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 4); + komodo_event* ev = state->Komodo_events[3]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'K'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 4); + auto itr = state->events.begin(); + std::advance(itr, 3); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type T (KMD height with timestamp) + { + const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_t_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 5); + komodo_event* ev = state->Komodo_events[4]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'K'); // changed from T to K + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 5); + auto itr = state->events.begin(); + std::advance(itr, 4); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type R (opreturn) + { + const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_r_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 6); + komodo_event* ev = state->Komodo_events[5]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'R'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 6); + auto itr = state->events.begin(); + std::advance(itr, 5); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_OPRETURN); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type V + { + const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_v_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 7); + komodo_event* ev = state->Komodo_events[6]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'V'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 7); + auto itr = state->events.begin(); + std::advance(itr, 6); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PRICEFEED); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + } + // record type B (rewind) + { + const std::string temp_filename = temp.native() + "/kmdtypeb.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_b_record(fp); + std::fclose(fp); + // verify file still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + // NOTE: B records are not read in. Unsure if this is on purpose or an oversight + int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* old way + EXPECT_EQ(state->Komodo_numevents, 7); + komodo_event* ev = state->Komodo_events[6]; + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, 'B'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 7); + /* + auto itr = state->events.begin(); + std::advance(itr, 6); + std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); + EXPECT_NE(ev2, nullptr); + EXPECT_EQ(ev2->height, 1); + EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_REWIND); + // the serialized version should match the input + EXPECT_TRUE(compare_serialization(full_filename, ev2)); + */ + } + // all together in 1 file + { + const std::string temp_filename = temp.native() + "/combined_state.tmp"; + char full_filename[temp_filename.size()+1]; + strcpy(full_filename, temp_filename.c_str()); + std::FILE* fp = std::fopen(full_filename, "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record(fp); + write_n_record(fp); + write_m_record(fp); + write_u_record(fp); + write_k_record(fp); + write_t_record(fp); + write_r_record(fp); + write_v_record(fp); + std::fclose(fp); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = (char*)"123456789012345"; + // attempt to read the file + int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + // compare results + EXPECT_EQ(result, 1); + /* ol d way + EXPECT_EQ(state->Komodo_numevents, 14); + komodo_event* ev1 = state->Komodo_events[7]; + EXPECT_EQ(ev1->height, 1); + EXPECT_EQ(ev1->type, 'P'); + */ + // check that the new way is the same + EXPECT_EQ(state->events.size(), 14); + auto itr = state->events.begin(); + std::advance(itr, 7); + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PUBKEYS); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_OPRETURN); + itr++; + } + { + EXPECT_EQ( (*itr)->height, 1); + EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PRICEFEED); itr++; } } From 6bbfe72ef5b776ea6954e7a3a0bc2566b03a8b8b Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 Aug 2021 08:41:15 -0500 Subject: [PATCH 46/58] handle KMD chain in test --- src/test-komodo/test_events.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index 884bb850232..6329238f73b 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -155,7 +155,7 @@ bool compare_serialization(const std::string& filename, std::shared_ptr in) */ TEST(TestEvents, komodo_faststateinit_test) { - char *symbol = "TST"; + char symbol[] = "TST"; strcpy(ASSETCHAINS_SYMBOL, symbol); KOMODO_EXTERNAL_NOTARIES = 1; @@ -565,7 +565,7 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) { // Nothing should be added to events if this is the komodo chain - char *symbol = "KMD"; + char symbol[] = "KMD"; ASSETCHAINS_SYMBOL[0] = 0; KOMODO_EXTERNAL_NOTARIES = 0; @@ -573,6 +573,9 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) boost::filesystem::create_directories(temp); try { + // NOTE: header contains a 5 byte header that is make up of + // an 8 bit identifier (i.e. 'P', 'N', etc.) + // plus a 32 bit height. Everything else is record specific // pubkey record { // create a binary file that should be readable by komodo From de6166bddd3ab27e501b28dba5bbbe795c3251c7 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 Aug 2021 15:22:02 -0500 Subject: [PATCH 47/58] Refactor komodo_state.NPOINTS --- src/komodo_notary.cpp | 60 +++++++++++++++++++++++-------------------- src/komodo_structs.h | 34 +++++++++++++++++++----- 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/komodo_notary.cpp b/src/komodo_notary.cpp index e6605bc0b80..82d748eb672 100644 --- a/src/komodo_notary.cpp +++ b/src/komodo_notary.cpp @@ -283,14 +283,12 @@ int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33, return(modval); } -//struct komodo_state *komodo_stateptr(char *symbol,char *dest); - -struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) +notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { - for (i=sp->NUM_NPOINTS-1; i>=0; i--) + for (i=sp->NPOINTS.size()-1; i>=0; i--) { *idx = i; np = &sp->NPOINTS[i]; @@ -299,38 +297,42 @@ struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) } } *idx = -1; - return(0); + return nullptr; } -struct notarized_checkpoint *komodo_npptr(int32_t height) +notarized_checkpoint *komodo_npptr(int32_t height) { int idx; return komodo_npptr_for_height(height, &idx); } -struct notarized_checkpoint *komodo_npptr_at(int idx) +notarized_checkpoint *komodo_npptr_at(int idx) { - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + char symbol[KOMODO_ASSETCHAIN_MAXLEN]; + char dest[KOMODO_ASSETCHAIN_MAXLEN]; + komodo_state *sp; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - if (idx < sp->NUM_NPOINTS) + if (idx < sp->NPOINTS.size()) return &sp->NPOINTS[idx]; - return(0); + return nullptr; } int32_t komodo_prevMoMheight() { static uint256 zero; - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; + char symbol[KOMODO_ASSETCHAIN_MAXLEN]; + char dest[KOMODO_ASSETCHAIN_MAXLEN]; + komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { - for (i=sp->NUM_NPOINTS-1; i>=0; i--) + for (auto &pt : sp->NPOINTS) { - np = &sp->NPOINTS[i]; - if ( np->MoM != zero ) - return(np->notarized_height); + if ( pt.MoM != zero ) + return pt.notarized_height; } } - return(0); + return 0; } int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp) @@ -402,22 +404,26 @@ int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,in int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp) { - struct notarized_checkpoint *np = 0; int32_t i=0,flag = 0; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; + notarized_checkpoint *np = 0; + int32_t i=0; + int32_t flag = 0; + char symbol[KOMODO_ASSETCHAIN_MAXLEN]; + char dest[KOMODO_ASSETCHAIN_MAXLEN]; + komodo_state *sp; + if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { - if ( sp->NUM_NPOINTS > 0 ) + if ( sp->NPOINTS.size() > 0 ) { - flag = 0; - if ( sp->last_NPOINTSi < sp->NUM_NPOINTS && sp->last_NPOINTSi > 0 ) + if ( sp->last_NPOINTSi < sp->NPOINTS.size() && sp->last_NPOINTSi > 0 ) { np = &sp->NPOINTS[sp->last_NPOINTSi-1]; if ( np->nHeight < nHeight ) { - for (i=sp->last_NPOINTSi; iNUM_NPOINTS; i++) + for (i=sp->last_NPOINTSi; iNPOINTS.size(); i++) { if ( sp->NPOINTS[i].nHeight >= nHeight ) { - //printf("flag.1 i.%d np->ht %d [%d].ht %d >= nHeight.%d, last.%d num.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight,sp->last_NPOINTSi,sp->NUM_NPOINTS); flag = 1; break; } @@ -429,11 +435,10 @@ int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *n if ( flag == 0 ) { np = 0; - for (i=0; iNUM_NPOINTS; i++) + for (i=0; iNPOINTS.size(); i++) { if ( sp->NPOINTS[i].nHeight >= nHeight ) { - //printf("i.%d np->ht %d [%d].ht %d >= nHeight.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight); break; } np = &sp->NPOINTS[i]; @@ -443,8 +448,7 @@ int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *n } if ( np != 0 ) { - //char str[65],str2[65]; printf("[%s] notarized_ht.%d\n",ASSETCHAINS_SYMBOL,np->notarized_height); - if ( np->nHeight >= nHeight || (i < sp->NUM_NPOINTS && np[1].nHeight < nHeight) ) + if ( np->nHeight >= nHeight || (i < sp->NPOINTS.size() && np[1].nHeight < nHeight) ) printf("warning: flag.%d i.%d np->ht %d [1].ht %d >= nHeight.%d\n",flag,i,np->nHeight,np[1].nHeight,nHeight); *notarized_hashp = np->notarized_hash; *notarized_desttxidp = np->notarized_desttxid; @@ -467,8 +471,8 @@ void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t not if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); std::lock_guard lock(komodo_mutex); - sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); - np = &sp->NPOINTS[sp->NUM_NPOINTS++]; + sp->NPOINTS.push_back(notarized_checkpoint()); + np = &sp->NPOINTS.back(); memset(np,0,sizeof(*np)); np->nHeight = nHeight; sp->NOTARIZED_HEIGHT = np->notarized_height = notarized_height; diff --git a/src/komodo_structs.h b/src/komodo_structs.h index ba2055956e8..a71327e2782 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -270,14 +270,36 @@ struct komodo_ccdata struct komodo_state { - uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID,MoM; - int32_t SAVEDHEIGHT,CURRENT_HEIGHT,NOTARIZED_HEIGHT,MoMdepth; + uint256 NOTARIZED_HASH; + uint256 NOTARIZED_DESTTXID; + uint256 MoM; + int32_t SAVEDHEIGHT; + int32_t CURRENT_HEIGHT; + int32_t NOTARIZED_HEIGHT; + int32_t MoMdepth; uint32_t SAVEDTIMESTAMP; - uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; - struct notarized_checkpoint *NPOINTS; - int32_t NUM_NPOINTS,last_NPOINTSi; + uint64_t deposited; + uint64_t issued; + uint64_t withdrawn; + uint64_t approved; + uint64_t redeemed; + uint64_t shorted; + // notarized checkpoint + std::vector NPOINTS; + int32_t last_NPOINTSi; + // events std::list> events; - uint32_t RTbufs[64][3]; uint64_t RTmask; + // RT + uint32_t RTbufs[64][3]; + uint64_t RTmask; + + /*** + * @brief add an event to the history collection + * @param symbol the chain symbol + * @param height the height + * @param in the event to add + * @returns true on success + */ bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); }; From f0a75323761dfab888648515db1ad6b71f5908ba Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 Aug 2021 15:23:34 -0500 Subject: [PATCH 48/58] Makefile.am cleanup --- src/Makefile.am | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 8926519b2e2..a81f18e6bf4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,16 +31,7 @@ BITCOIN_INCLUDES += -I$(srcdir)/snark BITCOIN_INCLUDES += -I$(srcdir)/snark/libsnark BITCOIN_INCLUDES += -I$(srcdir)/univalue/include -if TARGET_WINDOWS LIBBITCOIN_SERVER=libbitcoin_server.a -endif -if TARGET_DARWIN -LIBBITCOIN_SERVER=libbitcoin_server.a -endif -if TARGET_LINUX -LIBBITCOIN_SERVER=libbitcoin_server.a -endif - LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CLI=libbitcoin_cli.a From ce1245b9b700584654ce823cc9aad922d4c09761 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 Aug 2021 15:27:26 -0500 Subject: [PATCH 49/58] Remove unnecessary binary array --- src/komodo_structs.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index d3eb2206616..4bd4de3a746 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -301,10 +301,9 @@ event_opreturn::event_opreturn(FILE* fp, int32_t height) : event(EVENT_OPRETURN, uint16_t oplen; if ( fread(&oplen,1,sizeof(oplen),fp) != sizeof(oplen) ) throw parse_error("Unable to parse length of opreturn record"); - std::unique_ptr b(new uint8_t[oplen]); - if ( fread(b.get(), 1, oplen, fp) != oplen) + this->opret.resize(oplen); + if ( fread(this->opret.data(), 1, oplen, fp) != oplen) throw parse_error("Unable to parse binary data of opreturn"); - this->opret = std::vector( b.get(), b.get() + oplen); } std::ostream& operator<<(std::ostream& os, const event_opreturn& in) From ece5ff9a590c6cfab1bac9a983286e1d539308db Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 Aug 2021 18:47:46 -0500 Subject: [PATCH 50/58] Revert "Refactor komodo_state.NPOINTS" This reverts commit de6166bddd3ab27e501b28dba5bbbe795c3251c7. --- src/komodo_notary.cpp | 60 ++++++++++++++++++++----------------------- src/komodo_structs.h | 34 +++++------------------- 2 files changed, 34 insertions(+), 60 deletions(-) diff --git a/src/komodo_notary.cpp b/src/komodo_notary.cpp index 82d748eb672..e6605bc0b80 100644 --- a/src/komodo_notary.cpp +++ b/src/komodo_notary.cpp @@ -283,12 +283,14 @@ int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33, return(modval); } -notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) +//struct komodo_state *komodo_stateptr(char *symbol,char *dest); + +struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) { char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { - for (i=sp->NPOINTS.size()-1; i>=0; i--) + for (i=sp->NUM_NPOINTS-1; i>=0; i--) { *idx = i; np = &sp->NPOINTS[i]; @@ -297,42 +299,38 @@ notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx) } } *idx = -1; - return nullptr; + return(0); } -notarized_checkpoint *komodo_npptr(int32_t height) +struct notarized_checkpoint *komodo_npptr(int32_t height) { int idx; return komodo_npptr_for_height(height, &idx); } -notarized_checkpoint *komodo_npptr_at(int idx) +struct notarized_checkpoint *komodo_npptr_at(int idx) { - char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - char dest[KOMODO_ASSETCHAIN_MAXLEN]; - komodo_state *sp; + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - if (idx < sp->NPOINTS.size()) + if (idx < sp->NUM_NPOINTS) return &sp->NPOINTS[idx]; - return nullptr; + return(0); } int32_t komodo_prevMoMheight() { static uint256 zero; - char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - char dest[KOMODO_ASSETCHAIN_MAXLEN]; - komodo_state *sp; - + char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; int32_t i; struct komodo_state *sp; struct notarized_checkpoint *np = 0; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { - for (auto &pt : sp->NPOINTS) + for (i=sp->NUM_NPOINTS-1; i>=0; i--) { - if ( pt.MoM != zero ) - return pt.notarized_height; + np = &sp->NPOINTS[i]; + if ( np->MoM != zero ) + return(np->notarized_height); } } - return 0; + return(0); } int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp) @@ -404,26 +402,22 @@ int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,in int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp) { - notarized_checkpoint *np = 0; - int32_t i=0; - int32_t flag = 0; - char symbol[KOMODO_ASSETCHAIN_MAXLEN]; - char dest[KOMODO_ASSETCHAIN_MAXLEN]; - komodo_state *sp; - + struct notarized_checkpoint *np = 0; int32_t i=0,flag = 0; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) { - if ( sp->NPOINTS.size() > 0 ) + if ( sp->NUM_NPOINTS > 0 ) { - if ( sp->last_NPOINTSi < sp->NPOINTS.size() && sp->last_NPOINTSi > 0 ) + flag = 0; + if ( sp->last_NPOINTSi < sp->NUM_NPOINTS && sp->last_NPOINTSi > 0 ) { np = &sp->NPOINTS[sp->last_NPOINTSi-1]; if ( np->nHeight < nHeight ) { - for (i=sp->last_NPOINTSi; iNPOINTS.size(); i++) + for (i=sp->last_NPOINTSi; iNUM_NPOINTS; i++) { if ( sp->NPOINTS[i].nHeight >= nHeight ) { + //printf("flag.1 i.%d np->ht %d [%d].ht %d >= nHeight.%d, last.%d num.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight,sp->last_NPOINTSi,sp->NUM_NPOINTS); flag = 1; break; } @@ -435,10 +429,11 @@ int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *n if ( flag == 0 ) { np = 0; - for (i=0; iNPOINTS.size(); i++) + for (i=0; iNUM_NPOINTS; i++) { if ( sp->NPOINTS[i].nHeight >= nHeight ) { + //printf("i.%d np->ht %d [%d].ht %d >= nHeight.%d\n",i,np->nHeight,i,sp->NPOINTS[i].nHeight,nHeight); break; } np = &sp->NPOINTS[i]; @@ -448,7 +443,8 @@ int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *n } if ( np != 0 ) { - if ( np->nHeight >= nHeight || (i < sp->NPOINTS.size() && np[1].nHeight < nHeight) ) + //char str[65],str2[65]; printf("[%s] notarized_ht.%d\n",ASSETCHAINS_SYMBOL,np->notarized_height); + if ( np->nHeight >= nHeight || (i < sp->NUM_NPOINTS && np[1].nHeight < nHeight) ) printf("warning: flag.%d i.%d np->ht %d [1].ht %d >= nHeight.%d\n",flag,i,np->nHeight,np[1].nHeight,nHeight); *notarized_hashp = np->notarized_hash; *notarized_desttxidp = np->notarized_desttxid; @@ -471,8 +467,8 @@ void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t not if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"[%s] komodo_notarized_update nHeight.%d notarized_height.%d\n",ASSETCHAINS_SYMBOL,nHeight,notarized_height); std::lock_guard lock(komodo_mutex); - sp->NPOINTS.push_back(notarized_checkpoint()); - np = &sp->NPOINTS.back(); + sp->NPOINTS = (struct notarized_checkpoint *)realloc(sp->NPOINTS,(sp->NUM_NPOINTS+1) * sizeof(*sp->NPOINTS)); + np = &sp->NPOINTS[sp->NUM_NPOINTS++]; memset(np,0,sizeof(*np)); np->nHeight = nHeight; sp->NOTARIZED_HEIGHT = np->notarized_height = notarized_height; diff --git a/src/komodo_structs.h b/src/komodo_structs.h index a71327e2782..ba2055956e8 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -270,36 +270,14 @@ struct komodo_ccdata struct komodo_state { - uint256 NOTARIZED_HASH; - uint256 NOTARIZED_DESTTXID; - uint256 MoM; - int32_t SAVEDHEIGHT; - int32_t CURRENT_HEIGHT; - int32_t NOTARIZED_HEIGHT; - int32_t MoMdepth; + uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID,MoM; + int32_t SAVEDHEIGHT,CURRENT_HEIGHT,NOTARIZED_HEIGHT,MoMdepth; uint32_t SAVEDTIMESTAMP; - uint64_t deposited; - uint64_t issued; - uint64_t withdrawn; - uint64_t approved; - uint64_t redeemed; - uint64_t shorted; - // notarized checkpoint - std::vector NPOINTS; - int32_t last_NPOINTSi; - // events + uint64_t deposited,issued,withdrawn,approved,redeemed,shorted; + struct notarized_checkpoint *NPOINTS; + int32_t NUM_NPOINTS,last_NPOINTSi; std::list> events; - // RT - uint32_t RTbufs[64][3]; - uint64_t RTmask; - - /*** - * @brief add an event to the history collection - * @param symbol the chain symbol - * @param height the height - * @param in the event to add - * @returns true on success - */ + uint32_t RTbufs[64][3]; uint64_t RTmask; bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); }; From e5e40300fc26ce555fa9176e3cd65540d2bb7340 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 19 Aug 2021 07:39:43 -0500 Subject: [PATCH 51/58] Fix setting of event_notarized::dest --- src/komodo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo.cpp b/src/komodo.cpp index d8e19cc1a67..4791544d5fa 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -293,7 +293,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar if ( sp != 0 ) { std::shared_ptr evt = std::make_shared(height); - memcpy(evt->dest, dest, 65); + memcpy(evt->dest, dest, sizeof(evt->dest)-1); evt->blockhash = sp->NOTARIZED_HASH; evt->desttxid = sp->NOTARIZED_DESTTXID; evt->notarizedheight = sp->NOTARIZED_HEIGHT; From 052538e940da50786b1cb22bf1d7c3fb2d1615db Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 20 Aug 2021 08:15:51 -0500 Subject: [PATCH 52/58] missing and misordered includes for Windows --- src/komodo_jumblr.h | 2 +- src/uthash.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/komodo_jumblr.h b/src/komodo_jumblr.h index f767625b343..0ddd99b3403 100644 --- a/src/komodo_jumblr.h +++ b/src/komodo_jumblr.h @@ -15,11 +15,11 @@ #pragma once #include "uthash.h" // UT_hash_handle #include "komodo_cJSON.h" +#include "komodo_defs.h" #ifdef _WIN32 #include #endif -#include "komodo_defs.h" #define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" #define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" diff --git a/src/uthash.h b/src/uthash.h index 7b99c0133c0..2f1f15b76ca 100644 --- a/src/uthash.h +++ b/src/uthash.h @@ -27,6 +27,7 @@ #include /* memcmp,strlen */ #include /* ptrdiff_t */ #include /* exit() */ +#include /* These macros use decltype or the earlier __typeof GNU extension. As decltype is only available in newer compilers (VS2010 or gcc 4.3+ From 26260a38dd436c15cad7473e06e1be8c2bf757a7 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 20 Aug 2021 08:44:45 -0500 Subject: [PATCH 53/58] Adjust paths in tests for Windows compat --- src/cc/crypto777/OS_portable.h | 2 +- src/cc/dapps/cJSON.c | 2 +- src/cc/dapps/dappstd.c | 4 +- src/cc/dapps/oraclefeed.c | 2 +- src/cc/dapps/zmigrate.c | 2 +- src/cc/rogue/main.c | 4 +- src/komodo_cJSON.c | 2 +- src/komodo_cutils.cpp | 2 +- src/komodo_cutils.h | 2 +- src/komodo_gateway.cpp | 6 +- src/komodo_gateway.h | 4 +- src/test-komodo/test_events.cpp | 164 ++++++++++++-------------------- 12 files changed, 78 insertions(+), 118 deletions(-) diff --git a/src/cc/crypto777/OS_portable.h b/src/cc/crypto777/OS_portable.h index 2c85ed06ad8..4428876668a 100755 --- a/src/cc/crypto777/OS_portable.h +++ b/src/cc/crypto777/OS_portable.h @@ -370,7 +370,7 @@ void calc_base64_encodestr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_base64_decodestr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_hexstr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); void calc_unhexstr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len); -int32_t safecopy(char *dest,char *src,long len); +int32_t safecopy(char *dest,const char *src,long len); double dxblend(double *destp,double val,double decay); uint64_t calc_ipbits(char *ip_port); diff --git a/src/cc/dapps/cJSON.c b/src/cc/dapps/cJSON.c index e1d7801a1d6..6f9a2bdb336 100644 --- a/src/cc/dapps/cJSON.c +++ b/src/cc/dapps/cJSON.c @@ -766,7 +766,7 @@ int64_t conv_cJSON_float(cJSON *json,char *field) int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field) { - int32_t safecopy(char *dest,char *src,long len); + int32_t safecopy(char *dest,const char *src,long len); char *str; cJSON *obj; int32_t len; diff --git a/src/cc/dapps/dappstd.c b/src/cc/dapps/dappstd.c index b184999b14b..c27f79d21b3 100644 --- a/src/cc/dapps/dappstd.c +++ b/src/cc/dapps/dappstd.c @@ -107,7 +107,7 @@ char *parse_conf_line(char *line,char *field) return(clonestr(line)); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) @@ -180,7 +180,7 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) return(buf); } -uint8_t *OS_fileptr(long *allocsizep,char *fname) +uint8_t *OS_fileptr(long *allocsizep,const char *fname) { long filesize = 0; uint8_t *buf = 0; void *retptr; *allocsizep = 0; diff --git a/src/cc/dapps/oraclefeed.c b/src/cc/dapps/oraclefeed.c index 1db07722697..dec5249af9d 100644 --- a/src/cc/dapps/oraclefeed.c +++ b/src/cc/dapps/oraclefeed.c @@ -62,7 +62,7 @@ char *clonestr(char *str) return(clone); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) diff --git a/src/cc/dapps/zmigrate.c b/src/cc/dapps/zmigrate.c index 30d8fc5320a..1f97ff88e94 100644 --- a/src/cc/dapps/zmigrate.c +++ b/src/cc/dapps/zmigrate.c @@ -66,7 +66,7 @@ char *clonestr(char *str) return(clone); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) diff --git a/src/cc/rogue/main.c b/src/cc/rogue/main.c index 6e3c963f2b0..c3adbedd8ba 100644 --- a/src/cc/rogue/main.c +++ b/src/cc/rogue/main.c @@ -119,7 +119,7 @@ char *parse_conf_line(char *line,char *field) return(clonestr(line)); } -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) @@ -191,7 +191,7 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) return(buf); } -uint8_t *OS_fileptr(long *allocsizep,char *fname) +uint8_t *OS_fileptr(long *allocsizep,const char *fname) { long filesize = 0; uint8_t *buf = 0; void *retptr; *allocsizep = 0; diff --git a/src/komodo_cJSON.c b/src/komodo_cJSON.c index 6ab774f41c6..14c190de36d 100644 --- a/src/komodo_cJSON.c +++ b/src/komodo_cJSON.c @@ -156,7 +156,7 @@ int64_t conv_cJSON_float(cJSON *json,char *field) int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field) { - int32_t safecopy(char *dest,char *src,long len); + int32_t safecopy(char *dest,const char *src,long len); char *str; cJSON *obj; int32_t len; diff --git a/src/komodo_cutils.cpp b/src/komodo_cutils.cpp index de734fa72a9..4fa84fe6932 100644 --- a/src/komodo_cutils.cpp +++ b/src/komodo_cutils.cpp @@ -6,7 +6,7 @@ #include // sleep #endif -int32_t safecopy(char *dest,char *src,long len) +int32_t safecopy(char *dest,const char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) diff --git a/src/komodo_cutils.h b/src/komodo_cutils.h index 391ff0517b5..6d9a25c90ea 100644 --- a/src/komodo_cutils.h +++ b/src/komodo_cutils.h @@ -8,7 +8,7 @@ extern "C" { #include #include -int32_t safecopy(char *dest,char *src,long len); +int32_t safecopy(char *dest,const char *src,long len); long _stripwhite(char *buf,int accept); diff --git a/src/komodo_gateway.cpp b/src/komodo_gateway.cpp index 27df79a09da..d840df4574a 100644 --- a/src/komodo_gateway.cpp +++ b/src/komodo_gateway.cpp @@ -1244,7 +1244,7 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ else if ( func == 'R' ) // opreturn:*/ } -void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) +void *OS_loadfile(const char *fname,uint8_t **bufp,long *lenp,long *allocsizep) { FILE *fp; long filesize,buflen = *allocsizep; @@ -1282,7 +1282,7 @@ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) return(buf); } -uint8_t *OS_fileptr(long *allocsizep,char *fname) +uint8_t *OS_fileptr(long *allocsizep,const char *fname) { long filesize = 0; uint8_t *buf = 0; void *retptr; *allocsizep = 0; @@ -1354,7 +1354,7 @@ long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long return(newfpos); } -int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest) +int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest) { FILE *indfp; char indfname[1024]; uint8_t *filedata; long validated=-1,datalen,fpos,lastfpos; uint32_t tmp,prevpos100,indcounter,starttime; int32_t func,finished = 0; starttime = (uint32_t)time(NULL); diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index ce66ee66825..783d812d065 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -75,13 +75,13 @@ void komodo_stateind_set(struct komodo_state *sp,uint32_t *inds,int32_t n,uint8_ void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep); -uint8_t *OS_fileptr(long *allocsizep,char *fname); +uint8_t *OS_fileptr(long *allocsizep,const char *fname); long komodo_stateind_validate(struct komodo_state *sp,char *indfname,uint8_t *filedata,long datalen,uint32_t *prevpos100p,uint32_t *indcounterp,char *symbol,char *dest); long komodo_indfile_update(FILE *indfp,uint32_t *prevpos100p,long lastfpos,long newfpos,uint8_t func,uint32_t *indcounterp); -int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest); +int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); uint64_t komodo_interestsum(); diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index 6329238f73b..f2ae8ad5c16 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -5,7 +5,7 @@ #include #include -int32_t komodo_faststateinit(struct komodo_state *sp,char *fname,char *symbol,char *dest); +int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); struct komodo_state *komodo_stateptrget(char *base); extern int32_t KOMODO_EXTERNAL_NOTARIES; @@ -169,10 +169,8 @@ TEST(TestEvents, komodo_faststateinit_test) // pubkey record { // create a binary file that should be readable by komodo - const std::string temp_filename = temp.native() + "/kstate.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kstate.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_p_record(fp); std::fclose(fp); @@ -183,7 +181,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = nullptr; // attempt to read the file - int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -203,10 +201,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // notarized record { - const std::string temp_filename = temp.native() + "/notarized.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_n_record(fp); std::fclose(fp); @@ -217,7 +213,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -236,10 +232,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // notarized M record { - const std::string temp_filename = temp.native() + "/notarized.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_m_record(fp); std::fclose(fp); @@ -250,7 +244,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -271,10 +265,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // record type "U" (deprecated) { - const std::string temp_filename = temp.native() + "/type_u.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "type_u.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_u_record(fp); std::fclose(fp); @@ -285,7 +277,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -306,10 +298,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // record type K (KMD height) { - const std::string temp_filename = temp.native() + "/kmdtype.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtype.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_k_record(fp); std::fclose(fp); @@ -320,7 +310,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -341,10 +331,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // record type T (KMD height with timestamp) { - const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_t_record(fp); std::fclose(fp); @@ -355,7 +343,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -376,10 +364,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // record type R (opreturn) { - const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_r_record(fp); std::fclose(fp); @@ -390,7 +376,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -411,10 +397,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // record type V { - const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_v_record(fp); std::fclose(fp); @@ -425,7 +409,7 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -446,10 +430,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // record type B (rewind) { - const std::string temp_filename = temp.native() + "/kmdtypeb.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypeb.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_b_record(fp); std::fclose(fp); @@ -461,7 +443,7 @@ TEST(TestEvents, komodo_faststateinit_test) char* dest = (char*)"123456789012345"; // attempt to read the file // NOTE: B records are not read in. Unsure if this is on purpose or an oversight - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); /* old way @@ -485,10 +467,8 @@ TEST(TestEvents, komodo_faststateinit_test) } // all together in 1 file { - const std::string temp_filename = temp.native() + "/combined_state.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "combined_state.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_p_record(fp); write_n_record(fp); @@ -504,10 +484,10 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); - /* ol d way + /* old way EXPECT_EQ(state->Komodo_numevents, 14); komodo_event* ev1 = state->Komodo_events[7]; EXPECT_EQ(ev1->height, 1); @@ -579,10 +559,8 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) // pubkey record { // create a binary file that should be readable by komodo - const std::string temp_filename = temp.native() + "/kstate.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kstate.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_p_record(fp); std::fclose(fp); @@ -593,17 +571,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = nullptr; // attempt to read the file - int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // notarized record { - const std::string temp_filename = temp.native() + "/notarized.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_n_record(fp); std::fclose(fp); @@ -614,17 +590,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // notarized M record { - const std::string temp_filename = temp.native() + "/notarized.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "notarized.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_m_record(fp); std::fclose(fp); @@ -635,17 +609,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // record type "U" (deprecated) { - const std::string temp_filename = temp.native() + "/type_u.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "type_u.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_u_record(fp); std::fclose(fp); @@ -656,17 +628,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // record type K (KMD height) { - const std::string temp_filename = temp.native() + "/kmdtype.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtype.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_k_record(fp); std::fclose(fp); @@ -677,17 +647,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // record type T (KMD height with timestamp) { - const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_t_record(fp); std::fclose(fp); @@ -698,17 +666,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // record type R (opreturn) { - const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_r_record(fp); std::fclose(fp); @@ -719,17 +685,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // record type V { - const std::string temp_filename = temp.native() + "/kmdtypet.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypet.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_v_record(fp); std::fclose(fp); @@ -740,17 +704,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // record type B (rewind) { - const std::string temp_filename = temp.native() + "/kmdtypeb.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "kmdtypeb.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_b_record(fp); std::fclose(fp); @@ -762,17 +724,15 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) char* dest = (char*)"123456789012345"; // attempt to read the file // NOTE: B records are not read in. Unsure if this is on purpose or an oversight - int32_t result = komodo_faststateinit(state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit(state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); } // all together in 1 file { - const std::string temp_filename = temp.native() + "/combined_state.tmp"; - char full_filename[temp_filename.size()+1]; - strcpy(full_filename, temp_filename.c_str()); - std::FILE* fp = std::fopen(full_filename, "wb+"); + const std::string full_filename = (temp / "combined_state.tmp").string(); + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); EXPECT_NE(fp, nullptr); write_p_record(fp); write_n_record(fp); @@ -788,7 +748,7 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) EXPECT_NE(state, nullptr); char* dest = (char*)"123456789012345"; // attempt to read the file - int32_t result = komodo_faststateinit( state, full_filename, symbol, dest); + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); // compare results EXPECT_EQ(result, 1); EXPECT_EQ(state->events.size(), 0); From d99e7d205ba42ff1a2c4138a2910e56b91eec096 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sat, 18 Sep 2021 14:09:30 +0300 Subject: [PATCH 54/58] libbitcoin_server required -fPIC Since we added mini-gmp.c as a part of libbitcoin_server_a_SOURCES, -fPIC is required to avoid the linkage error: /usr/bin/ld: libbitcoin_server.a(libbitcoin_server_a-mini-gmp.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC libbitcoin_server.a: error adding symbols: Bad value collect2: error: ld returned 1 exit status TODO: In future we should totally (!) get rid of mini-gmp.c, for example, same way as i did here - https://github.com/DeckerSU/komodo/commit/bf14e827ea42f6b2b588e3d86b70c120834f1b43 , bcz actually we using only two functions from this mini-gmp.c - it's bitcoin_base58decode and bitcoin_base58encode, which are perfectly could be replaced with C++ analogs DecodeBase58, EncodeBase58 from base58.h --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index a81f18e6bf4..0f18d0249f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -278,6 +278,7 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: zcashd libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +libbitcoin_server_a_CPPFLAGS += -fPIC libbitcoin_server_a_SOURCES = \ sendalert.cpp \ addrman.cpp \ From 1239800be2f30721809a80487d7d22d31f744818 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sat, 18 Sep 2021 14:12:16 +0300 Subject: [PATCH 55/58] libcjson required -fPIC --- src/Makefile.am | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 0f18d0249f2..2266258bd7e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -83,11 +83,18 @@ $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " -%.o: %.c - $(CC) -c -o $@ $< +#%.o: %.c +# $(CC) -c -o $@ $< -$(LIBCJSON): cJSON.o komodo_cJSON.o komodo_cutils.o - $(AR) cr $(LIBCJSON) $^ +#$(LIBCJSON): cJSON.o komodo_cJSON.o komodo_cutils.o +# $(AR) cr $(LIBCJSON) $^ + +# libcjson build +LIBCJSON=libcjson.a +libcjson_a_SOURCES = cJSON.c \ + komodo_cJSON.c komodo_cutils.cpp +libcjson_a_CPPFLAGS=-fPIC +EXTRA_LIBRARIES += $(LIBCJSON) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: From 6ccbe4374d548a533dd68afa1523814abfcd7982 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 20 Sep 2021 12:35:11 +0300 Subject: [PATCH 56/58] (un)conditionally remove unused voutsum/sum --- src/komodo_notary.h | 1 + src/main.cpp | 3 +++ src/miner.cpp | 6 +----- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/komodo_notary.h b/src/komodo_notary.h index c722f934918..b285e7c47b2 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -21,6 +21,7 @@ #define KOMODO_MAINNET_START 178999 #define KOMODO_NOTARIES_HEIGHT1 814000 +#define KOMODO_NOTARIES_HEIGHT2 2588672 #define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" diff --git a/src/main.cpp b/src/main.cpp index 680850becd9..de26d1a6057 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3773,6 +3773,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001); blockReward += nFees + sum; + if ( ASSETCHAINS_SYMBOL[0] == 0 && pindex->GetHeight() >= KOMODO_NOTARIES_HEIGHT2) + blockReward -= sum; + if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && { uint64_t checktoshis; diff --git a/src/miner.cpp b/src/miner.cpp index 5f8e72141d9..e9e12019643 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -203,7 +203,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 } } else pk = _pk; - uint64_t deposits,voutsum=0; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); + uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); bool fNotarisationBlock = false; std::vector NotarisationNotaries; //fprintf(stderr,"create new block\n"); @@ -267,7 +267,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); uint32_t proposedTime = GetTime(); - voutsum = GetBlockSubsidy(nHeight,consensusParams) + 10000*COIN; // approx fees if (proposedTime == nMedianTimePast) { @@ -324,9 +323,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 txvalue = tx.GetValueOut(); if ( KOMODO_VALUETOOBIG(txvalue) != 0 ) continue; - //if ( KOMODO_VALUETOOBIG(txvalue + voutsum) != 0 ) // has been commented from main.cpp ? - // continue; - //voutsum += txvalue; if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 ) { fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure txid.%s nHeight.%d nTime.%u vs locktime.%u\n",tx.GetHash().ToString().c_str(),nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime); From df6c5f825c7a45c7ee88b935fe56f62441c4b88d Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 20 Sep 2021 12:35:48 +0300 Subject: [PATCH 57/58] bump KOMODO_VERSION to 0.7.1 --- src/rpc/misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 0062154654d..b111ef4a4e0 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -79,7 +79,7 @@ int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount); int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -#define KOMODO_VERSION "0.7.0" +#define KOMODO_VERSION "0.7.1" #define VERUS_VERSION "0.4.0g" extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; extern uint32_t ASSETCHAINS_CC; From 329fe33a46a7e77ddb026ac1658f4729a0320da0 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 20 Sep 2021 12:37:21 +0300 Subject: [PATCH 58/58] bump client version to 0.7.1 --- configure.ac | 2 +- src/clientversion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b169ec4c8c5..323590a43c2 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 7) -define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_BUILD, 0) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) diff --git a/src/clientversion.h b/src/clientversion.h index 4acff1b93ab..475da424d25 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -32,7 +32,7 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 7 -#define CLIENT_VERSION_REVISION 0 +#define CLIENT_VERSION_REVISION 1 #define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build