diff --git a/.gitignore b/.gitignore index 370866819..a62806be2 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,5 @@ qa/pull-tester/test.*/* /doc/doxygen/ libzcashconsensus.pc + +src/fiat/-usd diff --git a/src/assetchains b/src/assetchains index 32700d0da..f030f43d4 100755 --- a/src/assetchains +++ b/src/assetchains @@ -1,32 +1,35 @@ -./komodod -ac_name=USD -addnode=78.47.196.146 & -./komodod -ac_name=EUR -addnode=78.47.196.146 & -./komodod -ac_name=JPY -addnode=78.47.196.146 & -./komodod -ac_name=GBP -addnode=78.47.196.146 & -./komodod -ac_name=AUD -addnode=78.47.196.146 & -./komodod -ac_name=CAD -addnode=78.47.196.146 & -./komodod -ac_name=CHF -addnode=78.47.196.146 & -./komodod -ac_name=NZD -addnode=78.47.196.146 & -./komodod -ac_name=CNY -addnode=78.47.196.146 & -./komodod -ac_name=RUB -addnode=78.47.196.146 & -./komodod -ac_name=MXN -addnode=78.47.196.146 & -./komodod -ac_name=BRL -addnode=78.47.196.146 & -./komodod -ac_name=INR -addnode=78.47.196.146 & -./komodod -ac_name=HKD -addnode=78.47.196.146 & -./komodod -ac_name=TRY -addnode=78.47.196.146 & -./komodod -ac_name=ZAR -addnode=78.47.196.146 & -./komodod -ac_name=PLN -addnode=78.47.196.146 & -./komodod -ac_name=NOK -addnode=78.47.196.146 & -./komodod -ac_name=SEK -addnode=78.47.196.146 & -./komodod -ac_name=DKK -addnode=78.47.196.146 & -./komodod -ac_name=CZK -addnode=78.47.196.146 & -./komodod -ac_name=HUF -addnode=78.47.196.146 & -./komodod -ac_name=ILS -addnode=78.47.196.146 & -./komodod -ac_name=KRW -addnode=78.47.196.146 & -./komodod -ac_name=MYR -addnode=78.47.196.146 & -./komodod -ac_name=PHP -addnode=78.47.196.146 & -./komodod -ac_name=RON -addnode=78.47.196.146 & -./komodod -ac_name=SGD -addnode=78.47.196.146 & -./komodod -ac_name=THB -addnode=78.47.196.146 & -./komodod -ac_name=BGN -addnode=78.47.196.146 & -./komodod -ac_name=IDR -addnode=78.47.196.146 & -./komodod -ac_name=HRK -addnode=78.47.196.146 & +source pubkey.txt +echo $pubkey + +./komodod -pubkey=$pubkey -ac_name=USD -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=EUR -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=JPY -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=GBP -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=AUD -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=CAD -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=CHF -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=NZD -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=CNY -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=RUB -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=MXN -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=BRL -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=INR -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=HKD -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=TRY -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=ZAR -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=PLN -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=NOK -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=SEK -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=DKK -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=CZK -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=HUF -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=ILS -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=KRW -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=MYR -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=PHP -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=RON -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=SGD -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=THB -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=BGN -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=IDR -addnode=78.47.196.146 & +./komodod -pubkey=$pubkey -ac_name=HRK -addnode=78.47.196.146 & diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 6d802b873..0ea3f12b1 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -34,6 +34,8 @@ static bool fDaemon; extern char ASSETCHAINS_SYMBOL[16]; void komodo_gateway_iteration(char *symbol); +void komodo_iteration(char *symbol); +int32_t komodo_is_issuer(); void WaitForShutdown(boost::thread_group* threadGroup) { @@ -42,8 +44,10 @@ void WaitForShutdown(boost::thread_group* threadGroup) while (!fShutdown) { MilliSleep(2000); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) + if ( komodo_is_issuer() != 0 ) komodo_gateway_iteration(ASSETCHAINS_SYMBOL); + else komodo_iteration((char *)"EUR"); + fShutdown = ShutdownRequested(); } if (threadGroup) @@ -59,6 +63,7 @@ void WaitForShutdown(boost::thread_group* threadGroup) // extern int32_t IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,ASSETCHAIN_INIT; extern std::string NOTARY_PUBKEY; +int32_t komodo_is_issuer(); bool AppInit(int argc, char* argv[]) { @@ -97,10 +102,12 @@ bool AppInit(int argc, char* argv[]) try { void komodo_args(); - fprintf(stderr,"call komodo_args\n"); komodo_args(); + fprintf(stderr,"call komodo_args NOTARY_PUBKEY.(%s)\n",NOTARY_PUBKEY.c_str()); while ( ASSETCHAIN_INIT == 0 ) { + if ( komodo_is_issuer() != 0 ) + komodo_gateway_iteration(ASSETCHAINS_SYMBOL); sleep(1); } if (!boost::filesystem::is_directory(GetDataDir(false))) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 127983a17..991cc1333 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -137,7 +137,7 @@ void *chainparams_commandline(void *ptr) { sleep(1); } - fprintf(stderr,">>>>>>>> port.%u\n",ASSETCHAINS_PORT); + //fprintf(stderr,">>>>>>>> port.%u\n",ASSETCHAINS_PORT); if ( ASSETCHAINS_SYMBOL[0] != 0 ) { mainParams.SetDefaultPort(ASSETCHAINS_PORT); diff --git a/src/coins.cpp b/src/coins.cpp index 4272ed611..bbff5495b 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -384,6 +384,7 @@ const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const } uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); +extern char ASSETCHAINS_SYMBOL[16]; CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t tiptime) const { @@ -398,7 +399,8 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr nResult += value; interest = komodo_interest(nHeight,value,tx.nLockTime,tiptime); #ifdef KOMODO_ENABLE_INTEREST - nResult += interest; + if ( ASSETCHAINS_SYMBOL[0] == 0 && nHeight >= 60000 ) + nResult += interest; #endif (*interestp) += interest; } diff --git a/src/fiat/_usd b/src/fiat/_usd new file mode 100755 index 000000000..f5b373730 --- /dev/null +++ b/src/fiat/_usd @@ -0,0 +1,3 @@ + + +./komodo-cli -ac_name=-USD $1 $2 $3 $4 diff --git a/src/init.cpp b/src/init.cpp index 91412bbc3..1d0ffdb0b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1493,7 +1493,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_WALLET // Generate coins in the background if (pwalletMain) - GenerateBitcoins(GetBoolArg("-gen", true), pwalletMain, GetArg("-genproclimit", 1)); + GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1)); #endif // ********************************************************* Step 11: finished diff --git a/src/komodo.h b/src/komodo.h index 18fb286a4..e2e30224d 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -17,6 +17,8 @@ #define H_KOMODO_H // Todo: handle reorg: clear all entries above reorged height +// smooth consensus price +// #include #include @@ -24,14 +26,16 @@ #include 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 kheight,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout); -void komodo_init(); +void komodo_init(int32_t height); int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); char *komodo_issuemethod(char *method,char *params,uint16_t port); #define GENESIS_NBITS 0x1f00ffff +#define KOMODO_MINRATIFY 7 + #include "komodo_globals.h" #include "komodo_utils.h" -queue_t DepositsQ,PendingsQ; +//queue_t DepositsQ,PendingsQ; #include "cJSON.c" #include "komodo_bitcoind.h" @@ -148,7 +152,7 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar } if ( height <= 0 ) { - printf("early return: stateupdate height.%d\n",height); + //printf("early return: stateupdate height.%d\n",height); return; } if ( fp != 0 ) // write out funcid, height, other fields, call side effect function @@ -300,59 +304,75 @@ int32_t komodo_voutupdate(int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen, opretlen = scriptbuf[len++]; opretlen = (opretlen << 8) + scriptbuf[len++]; } - //for (k=0; k= 32*2+4 && strcmp(KOMODO_SOURCE,(char *)&scriptbuf[len+32*2+4]) == 0 ) + if ( j == 1 && opretlen >= 32*2+4 && strcmp(ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,(char *)&scriptbuf[len+32*2+4]) == 0 ) { len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&kmdtxid); len += iguana_rwnum(0,&scriptbuf[len],4,(uint8_t *)notarizedheightp); len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid); if ( *notarizedheightp > NOTARIZED_HEIGHT && *notarizedheightp < height ) { - printf("ht.%d NOTARIZED.%d KMD.%s BTCTXID.%s (%s)\n",height,*notarizedheightp,kmdtxid.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len]); + printf("ht.%d NOTARIZED.%d %s.%s %sTXID.%s (%s)\n",height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,kmdtxid.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),(char *)&scriptbuf[len]); NOTARIZED_HEIGHT = *notarizedheightp; NOTARIZED_HASH = kmdtxid; NOTARIZED_DESTTXID = desttxid; komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0); - } else printf("reject ht.%d NOTARIZED.%d %s.%s DESTTXID.%s (%s)\n",height,*notarizedheightp,KOMODO_SOURCE,kmdtxid.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len]); + } else printf("reject ht.%d NOTARIZED.%d %s.%s DESTTXID.%s (%s)\n",height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,kmdtxid.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len]); } else if ( i == 0 && j == 1 && opretlen == 149 ) komodo_paxpricefeed(height,&scriptbuf[len],opretlen); - else komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,value,&scriptbuf[len],opretlen,j); + else + { + //int32_t k; for (k=0; k 13 ) + if ( isspecial != 0 && numvalid >= KOMODO_MINRATIFY ) return(1); else return(0); } // Special tx have vout[0] -> CRYPTO777 -// with more than 13 pay2pubkey outputs -> ratify +// 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 void komodo_connectblock(CBlockIndex *pindex,CBlock& block) { + static int32_t hwmheight; uint64_t signedmask,voutmask; uint8_t scriptbuf[4096],pubkeys[64][33]; uint256 kmdtxid,btctxid,txhash; int32_t i,j,k,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count; - komodo_init(); + komodo_init(pindex->nHeight); + if ( pindex->nHeight > hwmheight ) + hwmheight = pindex->nHeight; + else + { + printf("hwmheight.%d vs pindex->nHeight.%d reorg.%d\n",hwmheight,pindex->nHeight,hwmheight-pindex->nHeight); + // reset komodostate + } + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + while ( KOMODO_REALTIME == 0 || time(NULL) <= KOMODO_REALTIME ) + { + fprintf(stderr,"komodo_connect.(%s) waiting for realtime RT.%u now.%u\n",ASSETCHAINS_SYMBOL,KOMODO_REALTIME,(uint32_t)time(NULL)); + sleep(3); + } + } KOMODO_INITDONE = (uint32_t)time(NULL); -#ifdef KOMODO_ISSUER - komodo_gateway_issuer(); -#else - komodo_gateway_redeemer(); -#endif if ( pindex != 0 ) { height = pindex->nHeight; txn_count = block.vtx.size(); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) + printf("%s ht.%d connect txn_count.%d\n",ASSETCHAINS_SYMBOL,height,txn_count); for (i=0; i 13 ) + if ( komodo_isratify(1,numvalid) >= KOMODO_MINRATIFY && numvouts > 13 ) { memset(&txhash,0,sizeof(txhash)); komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0); diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index d46c4eca0..4306548c1 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -23,6 +23,8 @@ #include #endif +#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7775",0,(char *)(cmdstr),0) + struct MemoryStruct { char *memory; size_t size; }; struct return_string { char *ptr; size_t len; }; @@ -137,7 +139,6 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char * * ************************************************************************/ - char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) { static int didinit,count,count2; static double elapsedsum,elapsedsum2; @@ -227,7 +228,8 @@ try_again: free(s.ptr); return(0); } - printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); + 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<GetBlockHash(); + seed = arith_uint256(hash.GetHex()).GetLow64(); + } + return(seed); +} + void komodo_disconnect(CBlockIndex *pindex,CBlock& block) { - komodo_init(); + //int32_t i; uint256 hash; + komodo_init(pindex->nHeight); + //hash = block.GetHash(); + //for (i=0; i<32; i++) + // printf("%02x",((uint8_t *)&hash)[i]); + //printf(" <- disconnect block\n"); //uint256 zero; //printf("disconnect ht.%d\n",pindex->nHeight); //memset(&zero,0,sizeof(zero)); @@ -373,7 +390,6 @@ void komodo_disconnect(CBlockIndex *pindex,CBlock& block) int32_t komodo_block2height(CBlock *block) { int32_t i,n,height = 0; uint8_t *ptr; - komodo_init(); #ifdef KOMODO_ZCASH ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data(); #else @@ -392,6 +408,7 @@ int32_t komodo_block2height(CBlock *block) } //printf(" <- coinbase.%d ht.%d\n",(int32_t)block->vtx[0].vin[0].scriptSig.size(),height); } + komodo_init(height); return(height); } @@ -402,14 +419,14 @@ void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block) #else uint8_t *ptr = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0]; #endif - komodo_init(); + komodo_init(0); memcpy(pubkey33,ptr+1,33); } void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) { CBlock block; - komodo_init(); + komodo_init(height); memset(pubkey33,0,33); if ( pindex != 0 ) { diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 79ff30f18..3279cfd95 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -17,170 +17,349 @@ struct pax_transaction { - struct queueitem DL; + UT_hash_handle hh; uint256 txid; uint64_t komodoshis,fiatoshis; + int32_t marked,height; uint16_t vout; - char symbol[4]; uint8_t rmd160[20],shortflag; -}; + char symbol[16],coinaddr[64]; uint8_t rmd160[20],shortflag; +} *PAX; -void komodo_gateway_deposits(CMutableTransaction& txNew) +uint64_t komodo_paxtotal() { - struct pax_transaction *ptr; uint8_t *script,opret[10000],data[10000]; int32_t i,len=0,opretlen=0,numvouts=1; - PENDING_KOMODO_TX = 0; - while ( (ptr= (struct pax_transaction *)queue_dequeue(&DepositsQ)) != 0 ) + struct pax_transaction *pax,*tmp; uint64_t total = 0; + /*pthread_mutex_lock(&komodo_mutex); + tmp = 0; + if ( PAX != 0 ) { - txNew.vout.resize(numvouts+1); - txNew.vout[numvouts].nValue = ptr->fiatoshis; - txNew.vout[numvouts].scriptPubKey.resize(25); - script = (uint8_t *)&txNew.vout[numvouts].scriptPubKey[0]; + pax = (struct pax_transaction *)PAX->hh.next; + while ( pax != 0 && pax != tmp && n++ < 1000000 ) + { + printf("PAX.[%p %p] pax.%p marked.%d fiat %.8f KMD %.8f\n",PAX->hh.next,PAX->hh.prev,pax,pax->marked,dstr(pax->fiatoshis),dstr(pax->komodoshis)); + if ( pax->marked == 0 ) + { + if ( komodo_is_issuer() != 0 ) + total += pax->fiatoshis; + else total += pax->komodoshis; + } + tmp = pax; + pax = (struct pax_transaction *)pax->hh.next; + } + } + pthread_mutex_unlock(&komodo_mutex); + if ( n >= 1000000 ) + printf("komodo_paxtotal n.%d iterations?\n",n);*/ + HASH_ITER(hh,PAX,pax,tmp) + { + if ( pax->marked == 0 ) + { + if ( komodo_is_issuer() != 0 ) + total += pax->fiatoshis; + else total += pax->komodoshis; + } + } + return(total); +} + +struct pax_transaction *komodo_paxfind(struct pax_transaction *space,uint256 txid,uint16_t vout) +{ + struct pax_transaction *pax; + pthread_mutex_lock(&komodo_mutex); + HASH_FIND(hh,PAX,&txid,sizeof(txid),pax); + if ( pax != 0 ) + memcpy(space,pax,sizeof(*pax)); + pthread_mutex_unlock(&komodo_mutex); + return(pax); +} + +struct pax_transaction *komodo_paxmark(int32_t height,struct pax_transaction *space,uint256 txid,uint16_t vout,int32_t mark) +{ + struct pax_transaction *pax; + pthread_mutex_lock(&komodo_mutex); + HASH_FIND(hh,PAX,&txid,sizeof(txid),pax); + if ( pax == 0 ) + { + pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); + pax->txid = txid; + pax->vout = vout; + HASH_ADD_KEYPTR(hh,PAX,&pax->txid,sizeof(pax->txid),pax); + //printf("ht.%d create pax.%p mark.%d\n",height,pax,mark); + } + if ( pax != 0 ) + { + pax->marked = mark; + //int32_t i; for (i=0; i<32; i++) + // printf("%02x",((uint8_t *)&txid)[i]); + //printf(" paxmark.ht %d vout%d\n",mark,vout); + memcpy(space,pax,sizeof(*pax)); + } + pthread_mutex_unlock(&komodo_mutex); + return(pax); +} + +void komodo_gateway_deposit(char *coinaddr,uint64_t value,int32_t shortflag,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,int32_t height) // assetchain context +{ + struct pax_transaction *pax; int32_t addflag = 0; + pthread_mutex_lock(&komodo_mutex); + HASH_FIND(hh,PAX,&txid,sizeof(txid),pax); + if ( pax == 0 ) + { + pax = (struct pax_transaction *)calloc(1,sizeof(*pax)); + pax->txid = txid; + pax->vout = vout; + HASH_ADD_KEYPTR(hh,PAX,&pax->txid,sizeof(pax->txid),pax); + //int32_t i; for (i=0; i<32; i++) + // printf("%02x",((uint8_t *)&txid)[i]); + //printf(" v.%d [%s] ht.%d create pax.%p\n",vout,ASSETCHAINS_SYMBOL,height,pax); + } + pthread_mutex_unlock(&komodo_mutex); + if ( coinaddr != 0 ) + { + strcpy(pax->coinaddr,coinaddr); + pax->komodoshis = value; + pax->shortflag = shortflag; + strcpy(pax->symbol,symbol); + pax->fiatoshis = fiatoshis; + memcpy(pax->rmd160,rmd160,20); + pax->height = height; + if ( pax->marked == 0 ) + printf("[%s] %p ADD DEPOSIT %s %.8f -> %s TO PAX ht.%d total %.8f\n",ASSETCHAINS_SYMBOL,pax,symbol,dstr(fiatoshis),coinaddr,height,dstr(komodo_paxtotal())); + else printf("%p MARKED.%d DEPOSIT %s %.8f -> %s TO PAX ht.%d\n",pax,pax->marked,symbol,dstr(fiatoshis),coinaddr,height); + } + else + { + pax->marked = height; + printf("pax.%p MARK DEPOSIT ht.%d\n",pax,height); + } +} + +int32_t komodo_issued_opreturn(uint8_t *shortflagp,char *base,uint256 *txids,uint16_t *vouts,uint8_t *opretbuf,int32_t opretlen) +{ + int32_t i,n=0,j,len; + if ( opretbuf[opretlen-5] == '-' ) + *shortflagp = 1; + else *shortflagp = 0; + for (i=0; i<4; i++) + base[i] = opretbuf[opretlen-4+i]; + if ( (strcmp(base,"KMD") == 0 && ASSETCHAINS_SYMBOL[0] == 0) || strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0 ) // shortflag + { + opretbuf++, opretlen--; + for (n=len=0; nmarked != 0 ) + continue; + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("pax.%p marked.%d %.8f -> %.8f\n",pax,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis)); + txNew->vout.resize(numvouts+1); + txNew->vout[numvouts].nValue = pax->fiatoshis; + txNew->vout[numvouts].scriptPubKey.resize(25); + script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0]; *script++ = 0x76; *script++ = 0xa9; *script++ = 20; - memcpy(script,ptr->rmd160,20), script += 20; + memcpy(script,pax->rmd160,20), script += 20; *script++ = 0x88; *script++ = 0xac; for (i=0; i<32; i++) { - printf("%02x",((uint8_t *)&ptr->txid)[i]); - data[len++] = ((uint8_t *)&ptr->txid)[i]; + //printf("%02x",((uint8_t *)&pax->txid)[i]); + data[len++] = ((uint8_t *)&pax->txid)[i]; } - data[len++] = ptr->vout & 0xff; - data[len++] = (ptr->vout >> 8) & 0xff; - printf(" vout.%u DEPOSIT %.8f\n",ptr->vout,(double)KOMODO_DEPOSIT/COIN); - PENDING_KOMODO_TX += ptr->fiatoshis; - numvouts++; - queue_enqueue((char *)"PENDINGS",&PendingsQ,&ptr->DL); + data[len++] = pax->vout & 0xff; + data[len++] = (pax->vout >> 8) & 0xff; + if ( strcmp(symbol,"KMD") != 0 ) + PENDING_KOMODO_TX += pax->fiatoshis; + else PENDING_KOMODO_TX += pax->komodoshis; + //printf(" vout.%u DEPOSIT %.8f <- paxdeposit.%s pending %.8f\n",pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,dstr(PENDING_KOMODO_TX)); + if ( numvouts++ >= 64 ) + break; } if ( numvouts > 1 ) { - opretlen = komodo_opreturnscript(opret,'I',data,len); - txNew.vout.resize(numvouts+1); - txNew.vout[numvouts].nValue = 0; - txNew.vout[numvouts].scriptPubKey.resize(opretlen); - script = (uint8_t *)&txNew.vout[numvouts].scriptPubKey[0]; + if ( shortflag != 0 ) + data[len++] = '-'; + for (i=0; symbol[i]!=0; i++) + data[len++] = symbol[i]; + data[len++] = 0; + opretlen = komodo_opreturnscript(opret,opcode,data,len); + txNew->vout.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); + printf("total numvouts.%d %.8f opretlen.%d\n",numvouts,dstr(PENDING_KOMODO_TX),opretlen); } - printf("total numvouts.%d %.8f\n",numvouts,dstr(PENDING_KOMODO_TX)); } -int32_t komodo_check_deposit(const CBlock& block) // verify above block is valid pax pricing +int32_t komodo_check_deposit(int32_t height,const CBlock& block) // verify above block is valid pax pricing { - // reenable rpc auth - return(0); -} - -void komodo_gateway_deposit(uint64_t value,int32_t shortflag,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout) // assetchain context -{ - struct pax_transaction *ptr; - ptr = (struct pax_transaction *)calloc(1,sizeof(*ptr)); - ptr->komodoshis = value; - ptr->fiatoshis = fiatoshis; - memcpy(ptr->symbol,symbol,3); - memcpy(ptr->rmd160,rmd160,20); - ptr->shortflag = shortflag; - ptr->txid = txid; - ptr->vout = vout; - KOMODO_DEPOSIT += fiatoshis; - queue_enqueue((char *)"DEPOSITS",&DepositsQ,&ptr->DL); -} - -int32_t komodo_gateway_depositremove(uint256 txid,uint16_t vout) // assetchain context -{ - int32_t iter,n=0; queue_t *Q; struct pax_transaction *ptr; struct queueitem *item; - for (iter=0; iter<2; iter++) + int32_t i,j,n,num,opretlen,offset=1,errs=0,matched=0; uint256 hash,txids[64]; uint8_t shortflag; char symbol[16],base[16]; uint16_t vouts[64]; uint8_t *script,opcode; struct pax_transaction *pax,space; + n = block.vtx[0].vout.size(); + script = (uint8_t *)block.vtx[0].vout[n-1].scriptPubKey.data(); + if ( n <= 2 || script[0] != 0x6a ) + return(0); + offset += komodo_scriptitemlen(&opretlen,&script[offset]); + //printf("checkdeposit n.%d [%02x] [%c] %d vs %d\n",n,script[0],script[offset],script[offset],'I'); + if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - Q = (iter == 0) ? &DepositsQ : &PendingsQ; - portable_mutex_lock(&Q->mutex); - if ( Q->list != 0 ) + opcode = 'X'; + strcpy(symbol,"KMD"); + } + else + { + strcpy(symbol,ASSETCHAINS_SYMBOL); + opcode = 'I'; + } + if ( script[offset] == opcode && opretlen < block.vtx[0].vout[n-1].scriptPubKey.size() ) + { + if ( (num= komodo_issued_opreturn(&shortflag,base,txids,vouts,&script[offset],opretlen)) > 0 ) { - item = &ptr->DL; - DL_FOREACH(Q->list,item) + for (i=1; itxid,&txid,sizeof(txid)) == 0 && ptr->vout == vout ) + if ( (pax= komodo_paxfind(&space,txids[i-1],vouts[i-1])) != 0 ) { - if ( KOMODO_DEPOSIT >= ptr->fiatoshis ) - KOMODO_DEPOSIT -= ptr->fiatoshis; - else KOMODO_DEPOSIT = 0; - printf("DELETE %.8f DEPOSIT %s %.8f\n",dstr(ptr->komodoshis),ptr->symbol,dstr(ptr->fiatoshis)); - DL_DELETE(Q->list,&ptr->DL); - n++; - free(ptr); - break; + if ( ((opcode == 'I' && pax->fiatoshis == block.vtx[0].vout[i].nValue) || (opcode == 'X' && pax->komodoshis == block.vtx[0].vout[i].nValue)) ) + { + if ( pax->marked != 0 ) + errs++; + else matched++; + //printf("errs.%d i.%d match %.8f == %.8f\n",errs,i,dstr(pax != 0 ? pax->fiatoshis:-1),dstr(block.vtx[0].vout[i].nValue)); + } + else + { + hash = block.GetHash(); + //for (j=0; j<32; j++) + // printf("%02x",((uint8_t *)&hash)[j]); + //printf(" ht.%d blockhash couldnt find vout.[%d]\n",height,i); + } } + else + { + //for (j=0; j<32; j++) + // printf("%02x",((uint8_t *)&txids[i-1])[j]); + //printf(" cant paxfind txid\n"); + } + komodo_paxmark(height,&space,txids[i-1],vouts[i-1],height); + } + if ( matched != num ) + { + //printf("matched.%d vs num.%d\n",matched,num); + if ( height > 60000 ) + return(-1); } } - portable_mutex_unlock(&Q->mutex); + //printf("opretlen.%d num.%d\n",opretlen,num); } - if ( queue_size(&DepositsQ) == 0 && queue_size(&PendingsQ) == 0 ) - KOMODO_DEPOSIT = PENDING_KOMODO_TX = 0; - return(n); + return(0); } const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout) { - uint8_t rmd160[20],addrtype,shortflag,pubkey33[33]; int32_t i,j,len,tokomodo=0; char base[4],coinaddr[64],destaddr[64]; int64_t fiatoshis,checktoshis; const char *typestr = "unknown"; -#ifdef KOMODO_ISSUER - tokomodo = 1; -#endif - if ( opretbuf[0] == ((tokomodo != 0) ? 'D' : 'W') ) + uint8_t rmd160[20],addrtype,shortflag,pubkey33[33]; int32_t i,j,n,len,tokomodo,kmdheight; char base[4],coinaddr[64],destaddr[64]; struct pax_transaction space; uint256 txids[64]; uint16_t vouts[64]; double diff; uint64_t seed; int64_t fiatoshis,checktoshis; const char *typestr = "unknown"; + tokomodo = (komodo_is_issuer() == 0); + if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) { - if ( opretlen == 34 ) + for (i=0; i %s ",dstr(fiatoshis),shortflag!=0?'-':'+',base,coinaddr); - 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)\n",dstr(checktoshis),dstr(value),destaddr); + checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,fiatoshis); typestr = "deposit"; -#ifdef KOMODO_ISSUER - if ( strncmp(KOMODO_SOURCE,base,strlen(base)) == 0 && value >= (9999*checktoshis)/10000 && shortflag == ASSETCHAINS_SHORTFLAG ) + printf("kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed); + diff = ((double)value / checktoshis) - 1.; + if ( diff < 0. ) + diff = -diff; + if ( kmdheight <= height ) { - komodo_gateway_deposit(value,shortflag,base,fiatoshis,rmd160,txid,vout); + if ( tokomodo == 0 && strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0 && shortflag == ASSETCHAINS_SHORTFLAG ) + { + if ( shortflag == 0 ) + { + 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 ( value >= checktoshis || (seed == 0 && diff < .01) ) + { + if ( komodo_paxfind(&space,txid,vout) == 0 ) + { + komodo_gateway_deposit(coinaddr,value,shortflag,base,fiatoshis,rmd160,txid,vout,kmdheight); + } else printf("duplicate deposit\n"); + } + } + else // short + { + for (i=0; i 0 && shortflag == ASSETCHAINS_SHORTFLAG ) { - for (j=0; j<32; j++) + for (i=0; i= offset+32*2+4 && strcmp((char *)&script[offset+32*2+4],"KMD") == 0 ) + if ( isspecial != 0 && len >= offset+32*2+4 && strcmp((char *)&script[offset+32*2+4],ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL) == 0 ) typestr = "notarized"; else if ( txi == 0 && vout == 1 && opretlen == 149 ) { @@ -209,43 +382,48 @@ void komodo_gateway_voutupdate(char *symbol,int32_t isspecial,int32_t height,int } else komodo_stateupdate(height,0,0,0,utxid,0,0,0,0,0,value,&script[offset],opretlen,vout); } - else if ( numvouts > 13 ) + else if ( numvouts >= KOMODO_MINRATIFY ) typestr = "ratify"; } int32_t komodo_gateway_tx(char *symbol,int32_t height,int32_t txi,char *txidstr,uint32_t port) { - char *retstr,params[256],*hexstr; uint8_t script[10000]; cJSON *json,*result,*vouts,*item,*sobj; int32_t vout,n,len,isspecial,retval = -1; uint64_t value; bits256 txid; + char *retstr,params[256],*hexstr; uint8_t script[10000]; cJSON *oldpub,*newpub,*json,*result,*vouts,*item,*sobj; int32_t vout,n,len,isspecial,retval = -1; uint64_t value; bits256 txid; sprintf(params,"[\"%s\", 1]",txidstr); if ( (retstr= komodo_issuemethod((char *)"getrawtransaction",params,port)) != 0 ) { if ( (json= cJSON_Parse(retstr)) != 0 ) { - if ( (result= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,result,(char *)"vout")) != 0 ) + if ( (result= jobj(json,(char *)"result")) != 0 ) { + oldpub = jobj(result,(char *)"vpub_old"); + newpub = jobj(result,(char *)"vpub_new"); retval = 0; - isspecial = 0; - txid = jbits256(result,(char *)"txid"); - for (vout=0; vout> 1; - if ( vout == 0 && ((memcmp(&hexstr[2],CRYPTO777_PUBSECPSTR,66) == 0 && len == 35) || (memcmp(&hexstr[6],CRYPTO777_RMD160STR,40) == 0 && len == 25)) ) - isspecial = 1; - else if ( len <= sizeof(script) ) + if ( (hexstr= jstr(sobj,(char *)"hex")) != 0 ) { - decode_hex(script,len,hexstr); - komodo_gateway_voutupdate(symbol,isspecial,height,txi,txid,vout,n,value,script,len); + len = (int32_t)strlen(hexstr) >> 1; + if ( vout == 0 && ((memcmp(&hexstr[2],CRYPTO777_PUBSECPSTR,66) == 0 && len == 35) || (memcmp(&hexstr[6],CRYPTO777_RMD160STR,40) == 0 && len == 25)) ) + isspecial = 1; + else if ( len <= sizeof(script) ) + { + decode_hex(script,len,hexstr); + komodo_gateway_voutupdate(symbol,isspecial,height,txi,txid,vout,n,value,script,len); + } } } } } - } + } else printf("error getting txids.(%s) %p\n",retstr,result); free_json(json); } free(retstr); @@ -255,7 +433,7 @@ int32_t komodo_gateway_tx(char *symbol,int32_t height,int32_t txi,char *txidstr, int32_t komodo_gateway_block(char *symbol,int32_t height,uint16_t port) { - char *retstr,*retstr2,params[128],*txidstr; int32_t i,n,retval = -1; cJSON *json,*tx,*result,*result2; + char *retstr,*retstr2,params[128],*txidstr; int32_t i,n,retval = -1; cJSON *json,*tx=0,*result=0,*result2; sprintf(params,"[%d]",height); if ( (retstr= komodo_issuemethod((char *)"getblockhash",params,port)) != 0 ) { @@ -276,17 +454,17 @@ int32_t komodo_gateway_block(char *symbol,int32_t height,uint16_t port) break; if ( i == n ) retval = 0; - else printf("error i.%d vs n.%d\n",i,n); - } + else printf("komodo_gateway_block ht.%d error i.%d vs n.%d\n",height,i,n); + } else printf("cant get result.%p or tx.%p\n",result,tx); free_json(json); - } + } else printf("cant parse2.(%s)\n",retstr2); free(retstr2); - } + } else printf("error getblock %s\n",params); } else printf("strlen.%ld (%s)\n",strlen(txidstr),txidstr); free_json(result); - } + } else printf("couldnt parse.(%s)\n",retstr); free(retstr); - } + } else printf("error from getblockhash %d\n",height); return(retval); } @@ -295,25 +473,32 @@ void komodo_gateway_iteration(char *symbol) char *retstr; int32_t i,kmdheight; cJSON *infoobj,*result; uint256 zero; uint16_t port = 7771; if ( KMDHEIGHT <= 0 ) KMDHEIGHT = 1; + KOMODO_REALTIME = 0; if ( (retstr= komodo_issuemethod((char *)"getinfo",0,port)) != 0 ) { if ( (infoobj= cJSON_Parse(retstr)) != 0 ) { if ( (result= jobj(infoobj,(char *)"result")) != 0 && (kmdheight= jint(result,(char *)"blocks")) != 0 ) { + //printf("gateway KMDHEIGHT.%d kmdheight.%d\n",KMDHEIGHT,kmdheight); for (i=0; i<1000 && KMDHEIGHT= kmdheight ) + KOMODO_REALTIME = (uint32_t)time(NULL); } free_json(infoobj); } @@ -321,20 +506,46 @@ void komodo_gateway_iteration(char *symbol) } else { - //printf("error from %s\n",symbol); + printf("error from %s\n",symbol); sleep(30); } } -#ifdef KOMODO_ISSUER -void komodo_gateway_issuer() // from "assetchain" connectblock() +void komodo_iteration(char *symbol) { - // check for redeems + char *retstr,*base,*coinaddr,*txidstr,cmd[512]; uint64_t value,fiatoshis; cJSON *array,*item; int32_t i,n,vout,shortflag,height; uint256 txid; uint8_t rmd160[20],addrtype; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + { + //[{"prev_hash":"5d5c9a49489b558de9e84f991f996dedaae6b9d0f157f82b2fec64662476d5cf","prev_vout":2,"EUR":0.78329000,"fiat":"EUR","height":57930,"KMD":0.10000000,"address":"RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5"}] + sprintf(cmd,"{\"agent\":\"dpow\",\"method\":\"pending\",\"fiat\":\"%s\"}",symbol); + if ( (retstr= issue_curl(cmd)) != 0 ) + { + if ( (array= cJSON_Parse(retstr)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 && height > 0 ) + { + fiatoshis = jdouble(item,base) * COIN; + decode_hex((uint8_t *)&txid,sizeof(txid),txidstr); + bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); + komodo_gateway_deposit(coinaddr,value,shortflag,base,fiatoshis,rmd160,txid,vout,height); + } + } + } + } + printf("retstr.(%s)\n",retstr); + free(retstr); + } + } } -#else - -void komodo_gateway_redeemer() // from "KMD" connectblock() -{ - -} -#endif diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 11062e866..e0516aa31 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -29,6 +29,6 @@ uint64_t ASSETCHAINS_SUPPLY = 10; int32_t NOTARIZED_HEIGHT,Num_nutxos,KMDHEIGHT = 43000; uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID; pthread_mutex_t komodo_mutex; -uint32_t KOMODO_INITDONE; +uint32_t KOMODO_INITDONE,KOMODO_REALTIME; char KMDUSERPASS[1024]; uint16_t BITCOIND_PORT = 7771; -uint64_t KOMODO_DEPOSIT,PENDING_KOMODO_TX; +uint64_t PENDING_KOMODO_TX; diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 0e5447087..a106f8503 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -13,7 +13,7 @@ * * ******************************************************************************/ -const char *Notaries[][2] = +const char *Notaries_genesis[][2] = { { "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, { "jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, @@ -60,18 +60,6 @@ struct knotary_entry { UT_hash_handle hh; uint8_t pubkey[33],notaryid; }; struct knotaries_entry { int32_t height,numnotaries; struct knotary_entry *Notaries; } Pubkeys[10000]; struct notarized_checkpoint { uint256 notarized_hash,notarized_desttxid; int32_t nHeight,notarized_height; } *NPOINTS; int32_t NUM_NPOINTS; -int32_t komodo_ratify_threshold(int32_t height,uint64_t signedmask) -{ - int32_t numnotaries,i,wt = 0; - numnotaries = Pubkeys[height / KOMODO_ELECTION_GAP].numnotaries; - for (i=0; i (numnotaries >> 1) || (wt > 7 && (signedmask & 3) != 0) ) - return(1); // N/2+1 || N/3 + devsig - else return(0); -} - void komodo_nutxoadd(int32_t height,int32_t notaryid,uint256 txhash,uint64_t voutmask,int32_t numvouts) { struct nutxo_entry *np; @@ -84,7 +72,7 @@ void komodo_nutxoadd(int32_t height,int32_t notaryid,uint256 txhash,uint64_t vou np->voutmask = voutmask; np->notaryid = notaryid; HASH_ADD_KEYPTR(hh,NUTXOS,&np->txhash,sizeof(np->txhash),np); - printf("Add NUTXO[%d] <- %s notaryid.%d t%u %s %llx\n",Num_nutxos,Notaries[notaryid][0],notaryid,komodo_txtime(txhash),txhash.ToString().c_str(),(long long)voutmask); + //printf("Add NUTXO[%d] <- %s notaryid.%d t%u %s %llx\n",Num_nutxos,Notaries[notaryid][0],notaryid,komodo_txtime(txhash),txhash.ToString().c_str(),(long long)voutmask); Num_nutxos++; pthread_mutex_unlock(&komodo_mutex); } @@ -101,6 +89,44 @@ int32_t komodo_nutxofind(int32_t height,uint256 txhash,int32_t vout) return(-1); } +int32_t komodo_ratify_threshold(int32_t height,uint64_t signedmask) +{ + int32_t htind,numnotaries,i,wt = 0; + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + return(2); + if ( (htind= KOMODO_PUBKEYS_HEIGHT(height) / KOMODO_ELECTION_GAP) == 1 ) + htind = 0; + numnotaries = Pubkeys[htind].numnotaries; + for (i=0; i (numnotaries >> 1) || (wt > 7 && (signedmask & 3) != 0) ) + return(1); + else return(0); +} + +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height) +{ + int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp; + if ( (htind= KOMODO_PUBKEYS_HEIGHT(height) / KOMODO_ELECTION_GAP) == 1 ) + htind = 0; + pthread_mutex_lock(&komodo_mutex); + n = Pubkeys[htind].numnotaries; + 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); + } + pthread_mutex_unlock(&komodo_mutex); + if ( mask == ((1LL << n)-1) ) + return(n); + printf("error retrieving notaries ht.%d got mask.%llx for n.%d\n",height,(long long)mask,n); + return(-1); +} + void komodo_notarysinit(int32_t height,uint8_t pubkeys[64][33],int32_t num) { int32_t k,i,htind; struct knotary_entry *kp; struct knotaries_entry N; @@ -120,8 +146,7 @@ void komodo_notarysinit(int32_t height,uint8_t pubkeys[64][33],int32_t num) } } N.numnotaries = num; - htind = KOMODO_PUBKEYS_HEIGHT(height) / KOMODO_ELECTION_GAP; - if ( htind == 1 ) + if ( (htind= KOMODO_PUBKEYS_HEIGHT(height) / KOMODO_ELECTION_GAP) == 1 ) htind = 0; for (i=htind; i= sizeof(Pubkeys)/sizeof(*Pubkeys) ) return(-1); + if ( (htind= KOMODO_PUBKEYS_HEIGHT(height) / KOMODO_ELECTION_GAP) == 1 ) + htind = 0; pthread_mutex_lock(&komodo_mutex); - HASH_FIND(hh,Pubkeys[height/KOMODO_ELECTION_GAP].Notaries,pubkey33,33,kp); + HASH_FIND(hh,Pubkeys[htind].Notaries,pubkey33,33,kp); pthread_mutex_unlock(&komodo_mutex); if ( kp != 0 ) { - if ( (numnotaries= Pubkeys[height/KOMODO_ELECTION_GAP].numnotaries) > 0 ) + if ( (numnotaries= Pubkeys[htind].numnotaries) > 0 ) { *notaryidp = kp->notaryid; modval = ((height % numnotaries) == kp->notaryid); @@ -195,25 +222,25 @@ int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *n return(0); } -void komodo_init() +void komodo_init(int32_t height) { static int didinit; uint256 zero; int32_t k,n; uint8_t pubkeys[64][33]; - if ( didinit == 0 ) + if ( height > didinit ) { - didinit = 1; - iguana_initQ(&DepositsQ,(char *)"Deposits"); - iguana_initQ(&PendingsQ,(char *)"Pendings"); - pthread_mutex_init(&komodo_mutex,NULL); - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); - n = (int32_t)(sizeof(Notaries)/sizeof(*Notaries)); - for (k=0; k 1000000*COIN ) + if ( basevolume > 10000*COIN ) + { + printf("paxcalc overflow %.8f\n",dstr(basevolume)); return(0); + } if ( (pvalb= pvals[baseid]) != 0 ) { if ( relid == MAX_CURRENCIES ) @@ -248,28 +317,35 @@ uint64_t komodo_paxcalc(uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t ba usdvol = komodo_paxvol(basevolume,baseusd) / MINDENOMS[baseid]; usdkmd = ((uint64_t)btcusd * 1000000000) / kmdbtc; //printf("base -> USD %llu, BTC %llu KMDUSD %llu\n",(long long)baseusd,(long long)btcusd,(long long)kmdusd); - printf("usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol); + //printf("usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu -> %.8f\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol,dstr(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd))); return(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd)); - } + } //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); - return(10 * ranked[baseid]); // map to percentage - } + //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(int32_t height,char *base,char *rel,uint64_t basevolume) +uint64_t _komodo_paxprice(int32_t height,char *base,char *rel,uint64_t basevolume) { int32_t baseid=-1,relid=-1,i; uint32_t *ptr; if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) @@ -284,6 +360,79 @@ uint64_t komodo_paxprice(int32_t height,char *base,char *rel,uint64_t basevolume return(0); } +uint64_t komodo_paxprice(uint64_t *seedp,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,seed,tolerance,den,densum,sum=0,votes[539]; + if ( basevolume > 10000*COIN ) + { + printf("komodo_paxprice overflow %.8f\n",dstr(basevolume)); + return(0); + } + numvotes = (int32_t)(sizeof(Peggy_inds)/sizeof(*Peggy_inds)); + memset(votes,0,sizeof(votes)); + for (sum=i=zeroes=nonz=0; i> 1) ) + 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 KMD %.8f\n",height,base,(double)fiatoshis/COIN,(double)komodoshis/COIN); if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) { PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 7a7b5c99b..2d8884a4d 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -796,10 +796,17 @@ int32_t komodo_baseid(char *origbase) for (i=0; i<=MAX_CURRENCIES; i++) if ( strcmp(CURRENCIES[i],base) == 0 ) return(i); - printf("illegal base.(%s) %s\n",origbase,base); + //printf("illegal base.(%s) %s\n",origbase,base); return(-1); } +int32_t komodo_is_issuer() +{ + if ( ASSETCHAINS_SYMBOL[0] != 0 && komodo_baseid(ASSETCHAINS_SYMBOL) >= 0 ) + return(1); + else return(0); +} + int32_t _unhex(char c) { if ( c >= '0' && c <= '9' ) @@ -1302,9 +1309,54 @@ void komodo_configfile(char *symbol,uint16_t port) } else printf("couldnt open.(%s)\n",fname); } +uint32_t komodo_assetmagic(char *symbol,uint64_t supply) +{ + uint8_t buf[512]; int32_t len = 0; + len = iguana_rwnum(1,&buf[len],sizeof(supply),(void *)&supply); + strcpy((char *)&buf[len],symbol); + len += strlen(symbol); + return(calc_crc32(0,buf,len)); +} + +int32_t komodo_shortflag(char *symbol) +{ + int32_t i,shortflag = 0; + if ( symbol[0] == '-' ) + { + shortflag = 1; + for (i=0; symbol[i+1]!=0; i++) + symbol[i] = symbol[i+1]; + symbol[i] = 0; + } + return(shortflag); +} + +uint16_t komodo_assetport(uint32_t magic,int32_t shortflag) +{ + return(8000 + shortflag*7777 + (magic % 7777)); +} + +uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,int32_t *shortflagp) +{ + *magicp = komodo_assetmagic(symbol,supply); + *shortflagp = komodo_shortflag(symbol); + return(komodo_assetport(*magicp,*shortflagp)); +} + +void komodo_ports(uint16_t ports[MAX_CURRENCIES]) +{ + int32_t i,shortflag; uint32_t magic; + for (i=0; i initialdownload\n"); return true; + } static bool lockIBDState = false; if (lockIBDState) + { + //fprintf(stderr,"lockIBDState true %d < %d\n",chainActive.Height(),pindexBestHeader->nHeight - 10); return false; - bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 || - pindexBestHeader->GetBlockTime() < GetTime() - chainParams.MaxTipAge()); + } + bool state; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + state = (chainActive.Height() < pindexBestHeader->nHeight - 24*6) || + pindexBestHeader->GetBlockTime() < (GetTime() - chainParams.MaxTipAge()); + else state = (chainActive.Height() < pindexBestHeader->nHeight - 100); if (!state) + { + //fprintf(stderr,"lockIBDState tru\n"); lockIBDState = true; + } return state; } @@ -1621,8 +1635,8 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight) { - // mark inputs spent - if (!tx.IsCoinBase()) { + if (!tx.IsCoinBase()) // mark inputs spent + { txundo.vprevout.reserve(tx.vin.size()); BOOST_FOREACH(const CTxIn &txin, tx.vin) { CCoinsModifier coins = inputs.ModifyCoins(txin.prevout.hash); @@ -1641,16 +1655,12 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach } } } - - // spend nullifiers - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { + BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { // spend nullifiers BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { inputs.SetNullifier(nf, true); } } - - // add outputs - inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); + inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); // add outputs } void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight) @@ -2243,7 +2253,8 @@ 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); CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus()); - if (block.vtx[0].GetValueOut() > blockReward) + if (block.vtx[0].vout[0].nValue > blockReward) + //if (block.vtx[0].GetValueOut() > blockReward) return state.DoS(100, error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0].GetValueOut(), blockReward), @@ -3039,6 +3050,7 @@ bool CheckBlockHeader(int32_t height,CBlockIndex *pindex, const CBlockHeader& bl return true; } +int32_t komodo_check_deposit(int32_t height,const CBlock& block); bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot) { // These are checks that are independent of context. @@ -3095,7 +3107,8 @@ bool CheckBlock(int32_t height,CBlockIndex *pindex,const CBlock& block, CValidat if (nSigOps > MAX_BLOCK_SIGOPS) return state.DoS(100, error("CheckBlock(): out-of-bounds SigOpCount"), REJECT_INVALID, "bad-blk-sigops", true); - + if ( komodo_check_deposit(height,block) < 0 ) + return(false); return true; } @@ -3302,8 +3315,10 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) { // Preliminary checks - bool checked = CheckBlock(komodo_block2height(pblock),0,*pblock, state); - + bool checked; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + checked = CheckBlock(komodo_block2height(pblock),0,*pblock, state); + else checked = CheckBlock(0,0,*pblock, state); { LOCK(cs_main); bool fRequested = MarkBlockAsReceived(pblock->GetHash()); diff --git a/src/miner.cpp b/src/miner.cpp index 0cce3e779..76c1ae3a0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -98,30 +98,35 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } +#define ASSETCHAINS_MINHEIGHT 100 int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize); -extern int32_t KOMODO_INITDONE; -extern uint64_t KOMODO_DEPOSIT; +uint64_t komodo_paxtotal(); +int32_t komodo_is_issuer(); +void komodo_gateway_deposits(CMutableTransaction *txNew,int32_t shortflag,char *symbol); +extern int32_t KOMODO_INITDONE,ASSETCHAINS_SHORTFLAG,KOMODO_REALTIME; extern char ASSETCHAINS_SYMBOL[16]; CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) { - const CChainParams& chainparams = Params(); + uint64_t deposits; const CChainParams& chainparams = Params(); // Create new block unique_ptr pblocktemplate(new CBlockTemplate()); if(!pblocktemplate.get()) return NULL; CBlock *pblock = &pblocktemplate->block; // pointer for convenience - while ( ASSETCHAINS_SYMBOL[0] != 0 && chainActive.Tip()->nHeight > 10 && mempool.GetTotalTxSize() <= 0 ) + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + fprintf(stderr,"start CreateNewBlock %s initdone.%d deposit %.8f mempool.%d RT.%u\n",ASSETCHAINS_SYMBOL,KOMODO_INITDONE,(double)komodo_paxtotal()/COIN,(int32_t)mempool.GetTotalTxSize(),KOMODO_REALTIME); + while ( mempool.GetTotalTxSize() <= 0 ) { - sleep(10); - if ( KOMODO_INITDONE == 0 || time(NULL) < KOMODO_INITDONE+60 ) + deposits = komodo_paxtotal(); + if ( KOMODO_INITDONE == 0 || time(NULL) < KOMODO_INITDONE+60 || KOMODO_REALTIME == 0 ) continue; - if ( KOMODO_DEPOSIT != 0 ) - { - printf("KOMODO_DEPOSIT %llu pblock->nHeight %d mempool.GetTotalTxSize(%d)\n",(long long)KOMODO_DEPOSIT,(int32_t)chainActive.Tip()->nHeight,(int32_t)mempool.GetTotalTxSize()); + if ( deposits != 0 ) break; - } + sleep(10); } + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("miner KOMODO_DEPOSIT %llu pblock->nHeight %d mempool.GetTotalTxSize(%d)\n",(long long)komodo_paxtotal(),(int32_t)chainActive.Tip()->nHeight,(int32_t)mempool.GetTotalTxSize()); // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios @@ -320,8 +325,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (fPrintPriority) { - LogPrintf("priority %.1f fee %s txid %s\n", - dPriority, feeRate.ToString(), tx.GetHash().ToString()); + LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString()); } // Add transactions that depend on this one to the priority queue @@ -351,27 +355,34 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) //txNew.nLockTime = (uint32_t)time(NULL) - 60; txNew.vin.resize(1); txNew.vin[0].prevout.SetNull(); - int32_t i,opretlen; uint8_t opret[256],*ptr; - if ( (opretlen= komodo_pax_opreturn(opret,sizeof(opret))) > 0 ) - { - txNew.vout.resize(2); - txNew.vout[1].scriptPubKey.resize(opretlen); - ptr = (uint8_t *)txNew.vout[1].scriptPubKey.data(); - for (i=0; i 0 ) + { + txNew.vout.resize(2); + txNew.vout[1].scriptPubKey.resize(opretlen); + ptr = (uint8_t *)txNew.vout[1].scriptPubKey.data(); + for (i=0; ivtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; - // Randomise nonce arith_uint256 nonce = UintToArith256(GetRandHash()); // Clear the top and bottom 16 bits (for local use as thread flags and counters) @@ -430,15 +441,25 @@ int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33) CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) { - CPubKey pubkey; CScript scriptPubKey; - if (!reservekey.GetReservedKey(pubkey)) - return NULL; - scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; + CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i; if ( USE_EXTERNAL_PUBKEY != 0 ) { //fprintf(stderr,"use notary pubkey\n"); scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; } + else + { + if (!reservekey.GetReservedKey(pubkey)) + return NULL; + scriptPubKey.resize(35); + ptr = (uint8_t *)pubkey.begin(); + script = (uint8_t *)scriptPubKey.data(); + script[0] = 33; + for (i=0; i<33; i++) + script[i+1] = ptr[i]; + script[34] = OP_CHECKSIG; + //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; + } return CreateNewBlock(scriptPubKey); } @@ -487,11 +508,22 @@ void static BitcoinMiner(CWallet *pwallet) unsigned int n = chainparams.EquihashN(); unsigned int k = chainparams.EquihashK(); + extern int32_t ASSETCHAIN_INIT,KOMODO_INITDONE; extern uint8_t NOTARY_PUBKEY33[33]; + int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33); + int32_t notaryid = -1; + while ( ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0 ) + { + sleep(1); + } + komodo_chosennotary(¬aryid,chainActive.Tip()->nHeight,NOTARY_PUBKEY33); - std::string solver = GetArg("-equihashsolver", "tromp"); + std::string solver; + if ( notaryid >= 0 || ASSETCHAINS_SYMBOL[0] != 0 ) + solver = "tromp"; + else solver = "default"; assert(solver == "tromp" || solver == "default"); LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k); - //fprintf(stderr,"Mining with %s\n",solver.c_str()); + fprintf(stderr,"Mining with %s\n",solver.c_str()); std::mutex m_cs; bool cancelSolver = false; boost::signals2::connection c = uiInterface.NotifyBlockTip.connect( @@ -502,6 +534,7 @@ void static BitcoinMiner(CWallet *pwallet) ); try { + //fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str()); while (true) { if (chainparams.MiningRequiresPeers()) @@ -517,11 +550,14 @@ void static BitcoinMiner(CWallet *pwallet) } if (!fvNodesEmpty && !IsInitialBlockDownload()) break; - MilliSleep(1000); + MilliSleep(5000); + //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload()); + } while (true); - //fprintf(stderr,"Found peers\n"); + //fprintf(stderr,"%s Found peers\n",ASSETCHAINS_SYMBOL); } - //fprintf(stderr,"create new block\n"); + //if ( ASSETCHAINS_SYMBOL[0] != 0 ) + // fprintf(stderr,"%s create new block\n",ASSETCHAINS_SYMBOL); // // Create new block // @@ -537,24 +573,23 @@ void static BitcoinMiner(CWallet *pwallet) } CBlock *pblock = &pblocktemplate->block; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - LogPrintf("Running ZcashMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(), - ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); - + LogPrintf("Running ZcashMiner.%s with %u transactions in block (%u bytes)\n",solver.c_str(),pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION)); // // Search // int32_t notaryid; uint32_t savebits; int64_t nStart = GetTime(); savebits = pblock->nBits; arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - if ( komodo_chosennotary(¬aryid,pindexPrev->nHeight+1,NOTARY_PUBKEY33) > 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_chosennotary(¬aryid,pindexPrev->nHeight+1,NOTARY_PUBKEY33) > 0 ) { hashTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS); Mining_start = (uint32_t)time(NULL); - //fprintf(stderr,"I am the chosen one for ht.%d\n",pindexPrev->nHeight+1); + fprintf(stderr,"I am the chosen one for %s ht.%d\n",ASSETCHAINS_SYMBOL,pindexPrev->nHeight+1); } else Mining_start = 0; Mining_height = pindexPrev->nHeight+1; while (true) { + //fprintf(stderr,"%s start mining loop\n",ASSETCHAINS_SYMBOL); // Hash state crypto_generichash_blake2b_state state; EhInitialiseState(n, k, state); @@ -568,23 +603,26 @@ void static BitcoinMiner(CWallet *pwallet) crypto_generichash_blake2b_state curr_state; curr_state = state; crypto_generichash_blake2b_update(&curr_state,pblock->nNonce.begin(),pblock->nNonce.size()); - // (x_1, x_2, ...) = A(I, V, n, k) LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",solver, pblock->nNonce.ToString()); - std::function)> validBlock = [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams] - (std::vector soln) { + (std::vector soln) + { // Write the solution to the hash and compute the result. LogPrint("pow", "- Checking solution against target\n"); pblock->nSolution = soln; solutionTargetChecks.increment(); if ( UintToArith256(pblock->GetHash()) > hashTarget ) - return false; - if ( Mining_start != 0 && time(NULL) < Mining_start+50 ) { - printf("Round robin diff sleep %d\n",(int32_t)(Mining_start+50-time(NULL))); - sleep(Mining_start+50-time(NULL)); + //if ( ASSETCHAINS_SYMBOL[0] != 0 ) + // printf("missed target\n"); + return false; + } + if ( ASSETCHAINS_SYMBOL[0] == 0 && Mining_start != 0 && time(NULL) < Mining_start+20 ) + { + printf("Round robin diff sleep %d\n",(int32_t)(Mining_start+20-time(NULL))); + sleep(Mining_start+20-time(NULL)); } // Found a solution SetThreadPriority(THREAD_PRIORITY_NORMAL); @@ -595,7 +633,10 @@ void static BitcoinMiner(CWallet *pwallet) std::lock_guard lock{m_cs}; cancelSolver = false; } - fprintf(stderr,"%s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height); + int32_t i; uint256 hash = pblock->GetHash(); + for (i=0; i<32; i++) + fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); + fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height); SetThreadPriority(THREAD_PRIORITY_LOWEST); // In regression test mode, stop mining after a block is found. if (chainparams.MineBlocksOnDemand()) { @@ -611,7 +652,7 @@ void static BitcoinMiner(CWallet *pwallet) }; // TODO: factor this out into a function with the same API for each solver. - if (solver == "tromp") { + if (solver == "tromp" && notaryid >= 0 ) { // Create solver and initialize it. equi eq(1); eq.setstate(&curr_state); @@ -662,14 +703,29 @@ void static BitcoinMiner(CWallet *pwallet) boost::this_thread::interruption_point(); // Regtest mode doesn't require peers if (vNodes.empty() && chainparams.MiningRequiresPeers()) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("no nodes, break\n"); break; + } if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("0xffff, break\n"); break; + } if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("timeout, break\n"); break; - if (pindexPrev != chainActive.Tip()) + } + if ( pindexPrev != chainActive.Tip() ) + { + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + printf("Tip advanced, break\n"); break; - + } // Update nNonce and nTime pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); pblock->nBits = savebits; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 607500c70..50175873e 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -382,24 +382,69 @@ Value gettxoutsetinfo(const Array& params, bool fHelp) uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime); uint32_t komodo_txtime(uint256 hash); -uint64_t komodo_paxprice(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 komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height); +char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); + +Value notaries(const Array& params, bool fHelp) +{ + Array a; Object ret; int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr; + if ( fHelp || params.size() != 1 ) + throw runtime_error("notaries height\n"); + LOCK(cs_main); + int32_t height = atoi(params[0].get_str().c_str()); + if ( height < 0 || height > chainActive.Height()+2000 ) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + else + { + if ( (n= komodo_notaries(pubkeys,height)) > 0 ) + { + for (i=0; i 4 ) throw runtime_error("paxprice \"base\" \"rel\" height amount\n"); LOCK(cs_main); - Object ret; uint64_t basevolume=0,relvolume; + Object ret; uint64_t basevolume=0,relvolume,seed; std::string base = params[0].get_str(); std::string rel = params[1].get_str(); int32_t height = atoi(params[2].get_str().c_str()); if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) basevolume = COIN; - relvolume = komodo_paxprice(height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); + relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); ret.push_back(Pair("base", base)); ret.push_back(Pair("rel", rel)); ret.push_back(Pair("height", height)); + ret.push_back(Pair("seed", seed)); if ( height < 0 || height > chainActive.Height() ) throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); else diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 81df5927a..30142ee82 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -107,7 +107,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "z_getoperationresult", 0}, { "z_importkey", 1 }, { "paxprice", 4 }, - { "paxprice2", 3 }, + { "paxprices", 3 }, + { "notaries", 1 }, }; class CRPCConvertTable diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 0808bc9ad..3a11eaf0c 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -605,15 +605,14 @@ Value getblocktemplate(const Array& params, bool fHelp) if (tx.IsCoinBase()) { // Show founders' reward if it is required - if (pblock->vtx[0].vout.size() > 1) { + //if (pblock->vtx[0].vout.size() > 1) { // Correct this if GetBlockTemplate changes the order - entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue)); - } + // entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue)); + //} entry.push_back(Pair("required", true)); txCoinbase = entry; - } else { + } else transactions.push_back(entry); - } } Object aux; @@ -804,8 +803,7 @@ Value getblocksubsidy(const Array& params, bool fHelp) "1. height (numeric, optional) The block height. If not provided, defaults to the current height of the chain.\n" "\nResult:\n" "{\n" - " \"miner\" : x.xxx (numeric) The mining reward amount in ZEC.\n" - " \"founders\" : x.xxx (numeric) The founders reward amount in ZEC.\n" + " \"miner\" : x.xxx (numeric) The mining reward amount in KMD.\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblocksubsidy", "1000") diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 801a4ff95..78a438d03 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -302,6 +302,7 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "verifychain", &verifychain, true }, { "blockchain", "paxprice", &paxprice, true }, { "blockchain", "paxprices", &paxprices, true }, + { "blockchain", "notaries", ¬aries, true }, /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true }, @@ -401,7 +402,8 @@ static const CRPCCommand vRPCCommands[] = { "wallet", "z_exportwallet", &z_exportwallet, true }, { "wallet", "z_importwallet", &z_importwallet, true }, - { "wallet", "paxdeposit", &paxdeposit, true } + { "wallet", "paxdeposit", &paxdeposit, true }, + { "wallet", "paxwithdraw", &paxwithdraw, true } #endif // ENABLE_WALLET }; @@ -965,15 +967,16 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn, conn->stream() << HTTPError(HTTP_UNAUTHORIZED, false) << std::flush; return false; } - JSONRequest jreq; try { // Parse request Value valRequest; if (!read_string(strRequest, valRequest)) + { + fprintf(stderr,"CANTPARSE.(%s)\n",strRequest.c_str()); throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); - + } // Return immediately if in warmup { LOCK(cs_rpcWarmup); diff --git a/src/rpcserver.h b/src/rpcserver.h index 135139ef9..765e27747 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -243,9 +243,11 @@ extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fH extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value notaries(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value paxprice(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value paxprices(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value paxdeposit(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value paxwithdraw(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp); diff --git a/src/util.cpp b/src/util.cpp index 19823cc05..a586a7516 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -401,19 +401,27 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread) } extern char ASSETCHAINS_SYMBOL[16]; +extern int32_t ASSETCHAINS_SHORTFLAG; boost::filesystem::path GetDefaultDataDir() { namespace fs = boost::filesystem; + char symbol[16]; + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + if ( ASSETCHAINS_SHORTFLAG != 0 ) + sprintf(symbol,"-%s",ASSETCHAINS_SYMBOL); + else strcpy(symbol,ASSETCHAINS_SYMBOL); + } else symbol[0] = 0; // Windows < Vista: C:\Documents and Settings\Username\Application Data\Zcash // Windows >= Vista: C:\Users\Username\AppData\Roaming\Zcash // Mac: ~/Library/Application Support/Zcash // Unix: ~/.zcash #ifdef WIN32 // Windows - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( symbol[0] == 0 ) return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo"; - else return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / ASSETCHAINS_SYMBOL; + else return GetSpecialFolderPath(CSIDL_APPDATA) / "Komodo" / symbol; #else fs::path pathRet; char* pszHome = getenv("HOME"); @@ -425,19 +433,19 @@ boost::filesystem::path GetDefaultDataDir() // Mac pathRet /= "Library/Application Support"; TryCreateDirectory(pathRet); - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( symbol[0] == 0 ) return pathRet / "Komodo"; else { pathRet /= "Komodo"; TryCreateDirectory(pathRet); - return pathRet / ASSETCHAINS_SYMBOL; + return pathRet / symbol; } #else // Unix - if ( ASSETCHAINS_SYMBOL[0] == 0 ) + if ( symbol[0] == 0 ) return pathRet / ".komodo"; - else return pathRet / ".komodo" / ASSETCHAINS_SYMBOL; + else return pathRet / ".komodo" / symbol; #endif #endif } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index be53660f6..892cf4fc1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -466,14 +466,19 @@ Value sendtoaddress(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } -uint64_t PAX_fiatdest(int32_t tokomodo,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); +uint64_t PAX_fiatdest(uint64_t *seedp,int32_t tokomodo,char *destaddr,uint8_t pubkey37[37],char *coinaddr,int32_t height,char *base,int64_t fiatoshis); int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen); #define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA" +extern char ASSETCHAINS_SYMBOL[16]; +int32_t komodo_is_issuer(); +int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp); Value paxdeposit(const Array& params, bool fHelp) { - uint64_t komodoshis = 0; char destaddr[64]; uint8_t i,pubkey33[33]; + uint64_t seed,komodoshis = 0; int32_t height; char destaddr[64]; uint8_t i,pubkey37[33]; bool fSubtractFeeFromAmount = false; + if ( komodo_is_issuer() != 0 ) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "paxdeposit only from KMD"); if (!EnsureWalletIsAvailable(fHelp)) return Value::null; if (fHelp || params.size() != 3) @@ -485,25 +490,62 @@ Value paxdeposit(const Array& params, bool fHelp) int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN; std::string base = params[2].get_str(); std::string dest; - komodoshis = PAX_fiatdest(0,destaddr,pubkey33,(char *)params[0].get_str().c_str(),chainActive.Tip()->nHeight,(char *)base.c_str(),fiatoshis); + height = chainActive.Tip()->nHeight; + komodoshis = PAX_fiatdest(&seed,0,destaddr,pubkey37,(char *)params[0].get_str().c_str(),height,(char *)base.c_str(),fiatoshis); dest.append(destaddr); CBitcoinAddress destaddress(CRYPTO777_KMDADDR); if (!destaddress.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address"); - for (i=0; i<33; i++) - printf("%02x",pubkey33[i]); - printf(" ht.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu\n",chainActive.Tip()->nHeight,(char *)params[0].get_str().c_str(),(char *)base.c_str(),(long long)fiatoshis,destaddr,(long long)komodoshis); + printf("%02x",pubkey37[i]); + printf(" ht.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu seed.%llx\n",height,(char *)params[0].get_str().c_str(),(char *)base.c_str(),(long long)fiatoshis,destaddr,(long long)komodoshis,(long long)seed); EnsureWalletIsUnlocked(); CWalletTx wtx; uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000; if ( fee < 10000 ) fee = 10000; - opretlen = komodo_opreturnscript(opretbuf,'D',pubkey33,33); + iguana_rwnum(1,&pubkey37[33],sizeof(height),&height); + opretlen = komodo_opreturnscript(opretbuf,'D',pubkey37,37); SendMoney(address.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis); return wtx.GetHash().GetHex(); } +Value paxwithdraw(const Array& params, bool fHelp) +{ + extern int32_t KMDHEIGHT,KOMODO_REALTIME; + CWalletTx wtx; std::string dest; int32_t height; uint64_t seed,komodoshis = 0; char destaddr[64]; uint8_t i,pubkey37[37]; bool fSubtractFeeFromAmount = false; + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + return(0); + if (!EnsureWalletIsAvailable(fHelp)) + return 0; + if (fHelp || params.size() != 2) + throw runtime_error("paxwithdraw \"address\" fiatamount"); + if ( KOMODO_REALTIME == 0 ) + return(0); + LOCK2(cs_main, pwalletMain->cs_wallet); + CBitcoinAddress address(params[0].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN; + komodoshis = PAX_fiatdest(&seed,1,destaddr,pubkey37,(char *)params[0].get_str().c_str(),KMDHEIGHT,ASSETCHAINS_SYMBOL,fiatoshis); + dest.append(destaddr); + CBitcoinAddress destaddress(CRYPTO777_KMDADDR); + if (!destaddress.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid dest Bitcoin address"); + for (i=0; i<33; i++) + printf("%02x",pubkey37[i]); + height = KMDHEIGHT; + printf(" ht.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu seed.%llx\n",height,(char *)params[0].get_str().c_str(),ASSETCHAINS_SYMBOL,(long long)fiatoshis,destaddr,(long long)komodoshis,(long long)seed); + EnsureWalletIsUnlocked(); + uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000; + if ( fee < 10000 ) + fee = 10000; + iguana_rwnum(1,&pubkey37[33],sizeof(height),&height); + opretlen = komodo_opreturnscript(opretbuf,'W',pubkey37,37); + SendMoney(destaddress.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,fiatoshis); + return wtx.GetHash().GetHex(); +} + Value listaddressgroupings(const Array& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index df9b8ee43..881b5256f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2392,6 +2392,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set return all selected outputs (we want all selected to go into the transaction for sure) if (coinControl && coinControl->HasSelected()) { + extern char ASSETCHAINS_SYMBOL[16]; uint64_t interest; BOOST_FOREACH(const COutput& out, vCoins) { @@ -2400,7 +2401,8 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, setvout[out.i].nValue; interest = komodo_interest(chainActive.Tip()->nHeight,out.tx->vout[out.i].nValue,out.tx->nLockTime,chainActive.Tip()->nTime); #ifdef KOMODO_ENABLE_INTEREST - nValueRet += interest; + if ( ASSETCHAINS_SYMBOL[0] == 0 && txheight >= 60000 ) + nValueRet += interest; #endif fprintf(stderr,"interest %llu from %llu lock.%u tip.%u\n",(long long)interest,(long long)out.tx->vout[out.i].nValue,out.tx->nLockTime,chainActive.Tip()->nTime); setCoinsRet.insert(make_pair(out.tx, out.i)); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index dfcbc1af8..c75f1f54d 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -58,7 +58,7 @@ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; //! Size of witness cache // Should be large enough that we can expect not to reorg beyond our cache // unless there is some exceptional network disruption. -static const unsigned int WITNESS_CACHE_SIZE = COINBASE_MATURITY; +static const unsigned int WITNESS_CACHE_SIZE = COINBASE_MATURITY+1; class CAccountingEntry; class CBlockIndex;