diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 86ed8f7b3..ad8da74d4 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -169,7 +169,7 @@ try_again: 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); @@ -198,7 +198,7 @@ try_again: 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); @@ -238,7 +238,7 @@ try_again: free(s.ptr); sleep((1<= 10000 sats PoS stake must be without txfee and in the last tx in the block at vout[0] */ +extern int32_t ASSETCHAINS_STREAM; uint64_t komodo_commission(const CBlock *pblock) { int32_t i,j,n=0,txn_count; uint64_t commission,total = 0; - txn_count = pblock->vtx.size(); - for (i=0; ivtx[i].vout.size(); - for (j=0; jvtx[i].vout[j].nValue; - } + txn_count = pblock->vtx.size(); + for (i=0; ivtx[i].vout.size(); + for (j=0; jvtx[i].vout[j].nValue; + } + } + //fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN)); + commission = ((total * ASSETCHAINS_COMMISSION) / COIN); + if ( commission < 10000 ) + commission = 0; + } + else + { + commission = 10000; } - //fprintf(stderr,"txn.%d n.%d commission total %.8f -> %.8f\n",txn_count,n,dstr(total),dstr((total * ASSETCHAINS_COMMISSION) / COIN)); - commission = ((total * ASSETCHAINS_COMMISSION) / COIN); - if ( commission < 10000 ) - commission = 0; return(commission); } @@ -1464,7 +1472,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_ int64_t komodo_checkcommission(CBlock *pblock,int32_t height) { int64_t checktoshis=0; uint8_t *script; - if ( ASSETCHAINS_COMMISSION != 0 ) + if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_STREAM != 0) { checktoshis = komodo_commission(pblock); if ( checktoshis > 10000 && pblock->vtx[0].vout.size() != 2 ) @@ -1570,14 +1578,33 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) if ( height == 1 ) { script = (uint8_t *)pblock->vtx[0].vout[0].scriptPubKey.data(); - if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) + if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) { return(-1); + } } else { if ( komodo_checkcommission(pblock,height) < 0 ) return(-1); } + if ( ASSETCHAINS_STREAM != 0 && height > 128 ) + { + int lasttx = ( pblock->vtx.size() -1 ); + printf("ABOUT TO CHECK LAST TX: %d\n",lasttx); + if ( lasttx == 0 ) + return(-1); + uint256 hash; CTransaction tx; + if (GetTransaction(pblock->vtx[lasttx].vin[0].prevout.hash,tx,hash,false)) + { + printf("CHECKING THE script pubkey\n"); + script = (uint8_t *)tx.vout[pblock->vtx[lasttx].vin[0].prevout.n].scriptPubKey.data(); + if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) { + printf("THE PUBKEY IS WRONG!\n"); + return(-1); + } + printf("THE PUBKEY IS RIGHT! \n"); + } + } } //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 ) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 379224b48..233f87fcf 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -90,7 +90,7 @@ struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout pax->marked = mark; //if ( height > 214700 || pax->height > 214700 ) // printf("mark ht.%d %.8f %.8f\n",pax->height,dstr(pax->komodoshis),dstr(pax->fiatoshis)); - + } pthread_mutex_unlock(&komodo_mutex); return(pax); @@ -203,9 +203,9 @@ int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t // return(0); incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4)); //41e77b91cb68dc2aa02fa88550eae6b6d44db676a7e935337b6d1392d9718f03cb0200305c90660400000000fbcbeb1f000000bde801006201000058e7945ad08ddba1eac9c9b6c8e1e97e8016a2d152 - + // 41e94d736ec69d88c08b5d238abeeca609c02357a8317e0d56c328bcb1c259be5d0200485bc80200000000404b4c000000000059470200b80b000061f22ba7d19fe29ac3baebd839af8b7127d1f9075553440046bb4cc7a3b5cd39dffe7206507a3482a00780e617f68b273cce9817ed69298d02001069ca1b0000000080f0fa02000000005b470200b90b000061f22ba7d19fe29ac3baebd839af8b7127d1f90755 - + //for (i=0; i 1 ) + if ( (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_STREAM != 0) && height > 1 ) { if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 ) { @@ -772,7 +772,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim 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; + 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' ) { @@ -1185,7 +1185,7 @@ 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:*/ @@ -1518,4 +1518,3 @@ void komodo_passport_iteration() printf("READY for %s RPC calls at %u! done PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,(uint32_t)time(NULL),ASSETCHAINS_SYMBOL,refid); } } - diff --git a/src/komodo_globals.h b/src/komodo_globals.h index f352b5333..569e29a5a 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -45,9 +45,9 @@ struct komodo_state KOMODO_STATES[34]; #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; -int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,KOMODO_CONNECTING = -1; +int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,ASSETCHAINS_STREAM,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,KOMODO_CONNECTING = -1; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; -std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY; +std::string ASSETCHAINS_OVERRIDE_ADDRESS,NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY; uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; @@ -55,7 +55,7 @@ uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT; uint32_t ASSETCHAINS_MAGIC = 2387029918; uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; +uint64_t ASSETCHAINS_FOUNDERS_REWARD,ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; uint32_t KOMODO_INITDONE; char KMDUSERPASS[8192],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771; diff --git a/src/komodo_utils.h b/src/komodo_utils.h index bfd59fd57..445841596 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1561,6 +1561,14 @@ void komodo_args(char *argv0) ASSETCHAINS_DECAY = GetArg("-ac_decay",0); ASSETCHAINS_COMMISSION = GetArg("-ac_perc",0); ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey",""); + ASSETCHAINS_FOUNDERS_REWARD = GetArg("-ac_freward",0); + ASSETCHAINS_OVERRIDE_ADDRESS = GetArg("-ac_address",""); + ASSETCHAINS_STREAM = GetArg("-ac_stream",0); + + if ( ASSETCHAINS_STREAM != 0 && ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_ENDSUBSIDY != 0 || ASSETCHAINS_REWARD != 0 || ASSETCHAINS_HALVING != 0 || ASSETCHAINS_DECAY != 0 || ASSETCHAINS_PRIVATE != 0 )) { + printf("ASSETCHAINS_STREAM cannot be used with:\n ASSETCHAINS_COMMISSION \n ASSETCHAINS_ENDSUBSIDY\n ASSETCHAINS_REWARD\n ASSETCHAINS_HALVING\n ASSETCHAINS_DECAY\n ASSETCHAINS_PRIVATE\n"); + exit(0); + } if ( (ASSETCHAINS_STAKED= GetArg("-ac_staked",0)) > 100 ) ASSETCHAINS_STAKED = 100; if ( ASSETCHAINS_STAKED != 0 && ASSETCHAINS_PRIVATE != 0 ) @@ -1589,8 +1597,15 @@ void komodo_args(char *argv0) { ASSETCHAINS_COMMISSION = 0; printf("ASSETCHAINS_COMMISSION needs an ASETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n"); - } - if ( ASSETCHAINS_ENDSUBSIDY != 0 || ASSETCHAINS_REWARD != 0 || ASSETCHAINS_HALVING != 0 || ASSETCHAINS_DECAY != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 ) + } else if ( ASSETCHAINS_STREAM != 0) { + printf("ASSETCHAINS_STREAM needs ASSETCHAINS_OVERRIDE_PUBKEY! \n"); + exit(0); + } + if ( ASSETCHAINS_STREAM != 0 && ASSETCHAINS_SUPPLY == 10 ) { + ASSETCHAINS_SUPPLY = 1000000; + printf("ASSETCHAINS_STREAM is set with no supply, setting supply at 1,000,000 coins. \n"); + } + if ( ASSETCHAINS_ENDSUBSIDY != 0 || ASSETCHAINS_REWARD != 0 || ASSETCHAINS_HALVING != 0 || ASSETCHAINS_DECAY != 0 || ASSETCHAINS_STREAM != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 ) { fprintf(stderr,"end.%llu blocks, reward %.8f halving.%llu blocks, decay.%llu perc %.4f%% ac_pub=[%02x...]\n",(long long)ASSETCHAINS_ENDSUBSIDY,dstr(ASSETCHAINS_REWARD),(long long)ASSETCHAINS_HALVING,(long long)ASSETCHAINS_DECAY,dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0]); extraptr = extrabuf; diff --git a/src/main.cpp b/src/main.cpp index 1ff5f8012..c6d2ee9e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1866,6 +1866,7 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW) //uint64_t komodo_moneysupply(int32_t height); extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern uint32_t ASSETCHAINS_MAGIC; +extern int32_t ASSETCHAINS_STREAM; extern uint64_t ASSETCHAINS_STAKED,ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY; extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE; @@ -1894,8 +1895,13 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) else if ( ASSETCHAINS_ENDSUBSIDY == 0 || nHeight < ASSETCHAINS_ENDSUBSIDY ) { if ( ASSETCHAINS_REWARD == 0 ) - return(10000); - else if ( ASSETCHAINS_ENDSUBSIDY != 0 && nHeight >= ASSETCHAINS_ENDSUBSIDY ) + { + if ( ASSETCHAINS_STREAM != 0 && nHeight > 128 ) + return(0); + else + return(10000); + } + else if ( ASSETCHAINS_ENDSUBSIDY != 0 && nHeight >= ASSETCHAINS_ENDSUBSIDY ) return(0); else { @@ -2961,6 +2967,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!view.HaveJoinSplitRequirements(tx)) return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); + + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + if ( ASSETCHAINS_STREAM != 0 ) + { + if ( block.vtx.size() == 1 && block.vtx[0].vout.size() == 2 && pindex->nHeight > ASSETCHAINS_MINHEIGHT) + { + return state.DoS(100, error("ConnectBlock(): There are no TX in this block, it is invalid!"), + REJECT_INVALID, "bad-block-no-transactions"); + } + } + } + if (fAddressIndex || fSpentIndex) { for (size_t j = 0; j < tx.vin.size(); j++) { @@ -3110,7 +3129,7 @@ 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()) + sum; - if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 ) + if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_STREAM != 0) ) { uint64_t checktoshis; if ( (checktoshis= komodo_commission((CBlock *)&block)) != 0 ) diff --git a/src/miner.cpp b/src/miner.cpp index 874c1b4f8..2e26cf6cd 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -64,7 +64,7 @@ public: set setDependsOn; CFeeRate feeRate; double dPriority; - + COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0) { } @@ -78,10 +78,10 @@ typedef boost::tuple TxPriority; class TxPriorityCompare { bool byFee; - + public: TxPriorityCompare(bool _byFee) : byFee(_byFee) { } - + bool operator()(const TxPriority& a, const TxPriority& b) { if (byFee) @@ -106,7 +106,7 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, #include "komodo_defs.h" -extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; +extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,ASSETCHAINS_STREAM,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE; extern uint64_t ASSETCHAINS_REWARD,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY; @@ -141,27 +141,27 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) // -blockversion=N to test forking scenarios if (Params().MineBlocksOnDemand()) pblock->nVersion = GetArg("-blockversion", pblock->nVersion); - + // Add dummy coinbase tx as first transaction pblock->vtx.push_back(CTransaction()); pblocktemplate->vTxFees.push_back(-1); // updated at end pblocktemplate->vTxSigOps.push_back(-1); // updated at end - + // Largest block you're willing to create: unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); - + // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE); nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize); - + // Minimum block size you want to create; block will be filled with free transactions // until there are no more or the block reaches this size: unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); - + // Collect memory pool transactions into the block CAmount nFees = 0; CBlockIndex* pindexPrev = 0; @@ -174,12 +174,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); CCoinsViewCache view(pcoinsTip); uint32_t expired; uint64_t commission; - + // Priority order to process transactions list vOrphan; // list memory doesn't move map > mapDependers; bool fPrintPriority = GetBoolArg("-printpriority", false); - + // This vector will be sorted into a priority queue: vector vecPriority; vecPriority.reserve(mempool.mapTx.size()); @@ -187,11 +187,11 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) mi != mempool.mapTx.end(); ++mi) { const CTransaction& tx = mi->GetTx(); - + int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) ? nMedianTimePast : pblock->GetBlockTime(); - + if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight)) { //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight)); @@ -256,16 +256,16 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) } if (fMissingInputs) continue; - + // Priority is sum(valuein * age) / modified_txsize unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); dPriority = tx.ComputePriority(dPriority, nTxSize); - + uint256 hash = tx.GetHash(); mempool.ApplyDeltas(hash, dPriority, nTotalIn); - + CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize); - + if (porphan) { porphan->dPriority = dPriority; @@ -274,27 +274,27 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) else vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx()))); } - + // Collect transactions into block uint64_t nBlockSize = 1000; uint64_t nBlockTx = 0; int64_t interest; int nBlockSigOps = 100; bool fSortedByFee = (nBlockPrioritySize <= 0); - + TxPriorityCompare comparer(fSortedByFee); std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); - + while (!vecPriority.empty()) { // Take highest priority transaction off the priority queue: double dPriority = vecPriority.front().get<0>(); CFeeRate feeRate = vecPriority.front().get<1>(); const CTransaction& tx = *(vecPriority.front().get<2>()); - + std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer); vecPriority.pop_back(); - + // Size limits unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); if (nBlockSize + nTxSize >= nBlockMaxSize-512) // room for extra autotx @@ -302,7 +302,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) //fprintf(stderr,"nBlockSize %d + %d nTxSize >= %d nBlockMaxSize\n",(int32_t)nBlockSize,(int32_t)nTxSize,(int32_t)nBlockMaxSize); continue; } - + // Legacy limits on sigOps: unsigned int nTxSigOps = GetLegacySigOpCount(tx); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) @@ -329,14 +329,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) comparer = TxPriorityCompare(fSortedByFee); std::make_heap(vecPriority.begin(), vecPriority.end(), comparer); } - + if (!view.HaveInputs(tx)) { //fprintf(stderr,"dont have inputs\n"); continue; } CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut(); - + nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) { @@ -354,7 +354,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) continue; } UpdateCoins(tx, view, nHeight); - + // Added pblock->vtx.push_back(tx); pblocktemplate->vTxFees.push_back(nTxFees); @@ -363,12 +363,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) ++nBlockTx; nBlockSigOps += nTxSigOps; nFees += nTxFees; - + if (fPrintPriority) { 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 if (mapDependers.count(hash)) { @@ -386,7 +386,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) } } } - + nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; blocktime = 1 + std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); @@ -411,7 +411,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) //printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->nHeight+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } - + // Create coinbase tx CMutableTransaction txNew = CreateNewContextualCMutableTransaction(chainparams.GetConsensus(), nHeight); txNew.vin.resize(1); @@ -426,9 +426,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) // Add fees txNew.vout[0].nValue += nFees; txNew.vin[0].scriptSig = CScript() << nHeight << OP_0; - + pblock->vtx[0] = txNew; - if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block)) != 0 ) + if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_STREAM != 0) && (commission= komodo_commission((CBlock*)&pblocktemplate->block)) != 0 ) { int32_t i; uint8_t *ptr; txNew.vout.resize(2); @@ -439,7 +439,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) for (i=0; i<33; i++) ptr[i+1] = ASSETCHAINS_OVERRIDE_PUBKEY33[i]; ptr[34] = OP_CHECKSIG; - //printf("autocreate commision vout\n"); + //printf("autocreate commission vout\n"); pblock->vtx[0] = txNew; } pblocktemplate->vTxFees[0] = -nFees; @@ -449,7 +449,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) nonce <<= 32; nonce >>= 16; pblock->nNonce = ArithToUint256(nonce); - + // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); pblock->hashReserved = uint256(); @@ -493,6 +493,26 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) return(0); } } + else if ( ASSETCHAINS_STREAM != 0 && ASSETCHAINS_SYMBOL[0] != 0 && nHeight > 128 ) + { + CMutableTransaction txStream = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1); + if ( komodo_notaryvin(txStream,ASSETCHAINS_OVERRIDE_PUBKEY33) > 0 ) + { + CAmount txfees = 10000; + pblock->vtx.push_back(txStream); + pblocktemplate->vTxFees.push_back(txfees); + pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStream)); + nFees += txfees; + pblocktemplate->vTxFees[0] = -nFees; + //*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees; + //fprintf(stderr,"added notaryvin\n"); + } + else + { + fprintf(stderr,"error adding streamer vin, the chain broke! \n"); + return(0); + } + } else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) ) { CValidationState state; @@ -527,7 +547,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) return pblocktemplate.release(); } - + /* #ifdef ENABLE_WALLET boost::optional GetMinerScriptPubKey(CReserveKey& reservekey) @@ -550,11 +570,11 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) return boost::optional(); #endif } - + CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; return scriptPubKey; } - + #ifdef ENABLE_WALLET CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) { @@ -564,7 +584,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) { boost::optional scriptPubKey = GetMinerScriptPubKey(); #endif - + if (!scriptPubKey) { return NULL; } @@ -592,7 +612,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& CMutableTransaction txCoinbase(pblock->vtx[0]); txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; assert(txCoinbase.vin[0].scriptSig.size() <= 100); - + pblock->vtx[0] = txCoinbase; pblock->hashMerkleRoot = pblock->BuildMerkleTree(); } @@ -610,12 +630,18 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey,int32_t nHeight,in { scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG; } + else if ( ASSETCHAINS_STREAM != 0 ) + { + if ( nHeight < 128 ) + scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG; + else + scriptPubKey = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG; + } else if ( USE_EXTERNAL_PUBKEY != 0 ) { //fprintf(stderr,"use notary pubkey\n"); scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; - } - else + } else { if (!reservekey.GetReservedKey(pubkey)) { @@ -661,7 +687,7 @@ static bool ProcessBlockFound(CBlock* pblock) { LogPrintf("%s\n", pblock->ToString()); LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.LastTip()->nHeight+1); - + // Found a solution { //LOCK(cs_main); @@ -676,11 +702,11 @@ static bool ProcessBlockFound(CBlock* pblock) for (i=31; i>=0; i--) fprintf(stderr,"%02x",((uint8_t *)&hash)[i]); fprintf(stderr," <- chainTip (stale)\n"); - + return error("KomodoMiner: generated block is stale"); } } - + #ifdef ENABLE_WALLET // Remove key from key pool if ( IS_KOMODO_NOTARY == 0 ) @@ -704,7 +730,7 @@ static bool ProcessBlockFound(CBlock* pblock) CValidationState state; if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL)) return error("KomodoMiner: ProcessNewBlock, block not accepted"); - + TrackMinedBlock(pblock->GetHash()); komodo_broadcast(pblock,16); return true; @@ -728,15 +754,15 @@ void static BitcoinMiner() SetThreadPriority(THREAD_PRIORITY_LOWEST); RenameThread("komodo-miner"); const CChainParams& chainparams = Params(); - + #ifdef ENABLE_WALLET // Each thread has its own key CReserveKey reservekey(pwallet); #endif - + // Each thread has its own counter unsigned int nExtraNonce = 0; - + unsigned int n = chainparams.EquihashN(); unsigned int k = chainparams.EquihashK(); uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1; @@ -767,7 +793,7 @@ void static BitcoinMiner() } ); miningTimer.start(); - + try { if ( ASSETCHAINS_SYMBOL[0] != 0 ) fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str()); @@ -790,7 +816,7 @@ void static BitcoinMiner() break; MilliSleep(15000); //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload()); - + } while (true); //fprintf(stderr,"%s Found peers\n",ASSETCHAINS_SYMBOL); miningTimer.start(); @@ -840,14 +866,19 @@ void static BitcoinMiner() { if ( ASSETCHAINS_REWARD == 0 ) { - if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT ) + int minvoutsize = 1; + int minvtxsize = 1; + if ( ASSETCHAINS_STREAM != 0 ) + minvoutsize = 2; + minvtxsize = 2; + if ( pblock->vtx.size() == minvtxsize && pblock->vtx[0].vout.size() == minvoutsize && Mining_height > ASSETCHAINS_MINHEIGHT ) { static uint32_t counter; if ( counter++ < 10 ) fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL); sleep(10); continue; - } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT); + } else fprintf(stderr,"%s tx.%d vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx.size(),(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT); } } IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); @@ -926,13 +957,13 @@ void static BitcoinMiner() } while (true) { - if ( KOMODO_INSYNC == 0 ) + /*if ( KOMODO_INSYNC == 0 && Mining_height > ASSETCHAINS_MINHEIGHT ) { fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height); if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN ) KOMODO_INSYNC = 1; sleep(3); - } + } */ // Hash state KOMODO_CHOSEN_ONE = 0; crypto_generichash_blake2b_state state; @@ -1054,13 +1085,13 @@ void static BitcoinMiner() std::lock_guard lock{m_cs}; return cancelSolver; }; - + // TODO: factor this out into a function with the same API for each solver. if (solver == "tromp" ) { //&& notaryid >= 0 ) { // Create solver and initialize it. equi eq(1); eq.setstate(&curr_state); - + // Initialization done, start algo driver. eq.digit0(0); eq.xfull = eq.bfull = eq.hfull = 0; @@ -1072,7 +1103,7 @@ void static BitcoinMiner() } eq.digitK(0); ehSolverRuns.increment(); - + // Convert solution indices to byte array (decompress) and pass it to validBlock method. for (size_t s = 0; s < eq.nsols; s++) { LogPrint("pow", "Checking solution %d\n", s+1); @@ -1081,7 +1112,7 @@ void static BitcoinMiner() index_vector[i] = eq.sols[s][i]; } std::vector sol_char = GetMinimalFromIndices(index_vector, DIGITBITS); - + if (validBlock(sol_char)) { // If we find a POW solution, do not try other solutions // because they become invalid as we created a new block in blockchain. @@ -1108,7 +1139,7 @@ void static BitcoinMiner() cancelSolver = false; } } - + // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); // Regtest mode doesn't require peers @@ -1178,7 +1209,7 @@ void static BitcoinMiner() miningTimer.stop(); c.disconnect(); } - + #ifdef ENABLE_WALLET void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) #else @@ -1186,10 +1217,10 @@ void static BitcoinMiner() #endif { static boost::thread_group* minerThreads = NULL; - + if (nThreads < 0) nThreads = GetNumCores(); - + if (minerThreads != NULL) { minerThreads->interrupt_all(); @@ -1201,7 +1232,7 @@ void static BitcoinMiner() nThreads = 1; if (nThreads == 0 || !fGenerate) return; - + minerThreads = new boost::thread_group(); for (int i = 0; i < nThreads; i++) { #ifdef ENABLE_WALLET @@ -1211,5 +1242,5 @@ void static BitcoinMiner() #endif } } - + #endif // ENABLE_MINING diff --git a/src/pow.cpp b/src/pow.cpp index 1291e445e..9c8f68586 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -20,31 +20,39 @@ #include "librustzcash.h" #endif // ENABLE_RUST uint32_t komodo_chainactive_timestamp(); +extern int32_t ASSETCHAINS_STREAM; unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { - unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); - // Genesis block - if (pindexLast == NULL ) - return nProofOfWorkLimit; + if ( ASSETCHAINS_STREAM == 0) + { + unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); + // Genesis block + if (pindexLast == NULL ) + return nProofOfWorkLimit; - // Find the first block in the averaging interval - const CBlockIndex* pindexFirst = pindexLast; - arith_uint256 bnTot {0}; - for (int i = 0; pindexFirst && i < params.nPowAveragingWindow; i++) { - arith_uint256 bnTmp; - bnTmp.SetCompact(pindexFirst->nBits); - bnTot += bnTmp; - pindexFirst = pindexFirst->pprev; + // Find the first block in the averaging interval + const CBlockIndex* pindexFirst = pindexLast; + arith_uint256 bnTot {0}; + for (int i = 0; pindexFirst && i < params.nPowAveragingWindow; i++) { + arith_uint256 bnTmp; + bnTmp.SetCompact(pindexFirst->nBits); + bnTot += bnTmp; + pindexFirst = pindexFirst->pprev; + } + + // Check we have enough blocks + if (pindexFirst == NULL) + return nProofOfWorkLimit; + + arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow}; + + return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params); + } + else + { + return 537857807; } - - // Check we have enough blocks - if (pindexFirst == NULL) - return nProofOfWorkLimit; - - arith_uint256 bnAvg {bnTot / params.nPowAveragingWindow}; - - return CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params); } unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index e9cf54bb4..0a00a614c 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -257,6 +257,218 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) return result; } +unsigned char hexval(unsigned char c) +{ + if ('0' <= c && c <= '9') + return c - '0'; + else if ('a' <= c && c <= 'f') + return c - 'a' + 10; + else if ('A' <= c && c <= 'F') + return c - 'A' + 10; + else abort(); +} + +void hex2ascii(const string& in, string& out) +{ + out.clear(); + out.reserve(in.length() / 2); + for (string::const_iterator p = in.begin(); p != in.end(); p++) + { + unsigned char c = hexval(*p); + p++; + if (p == in.end()) break; // incomplete last digit - should report error + c = (c << 4) + hexval(*p); // + takes precedence over << + out.push_back(c); + } +} + +UniValue getdatafromblock(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getdatafromblock \"hash|height\" true/false\n" + "\nReturns all the data sent via streamer in block if there was any data in it.\n" + "\nArguments:\n" + "1. \"hash|height\" (string, required) The block hash or height\n" + "2. \"true/false\" (bool, optional) if false do not return the actual data. Default true.\n" + "\nResult (for verbose = true):\n" + "{\n" + " \"streamid\" : \"string\", (string) the name of the stream.\n" + " \"firsttxid\" : \"hash\", (string) the first transaction of the stream.\n" + " \"firstblockheight\" : \"n\", (numeric) the block the stream starts in.\n" + " \"firstdeqid\" : n, (numeric) The sequence id of the first data chunk in this block\n" + " \"lastseqid\" : n, (numeric) The sequence id of the last data chunk in this block\n" + " \"data\" : \"xxxx\", (string) A hex string containing all the data chunks in this block.\n" + "}\n" + "\nResult (for verbose=false):\n" + " \"streamid\" : \"string\", (string) the name of the stream.\n" + " \"firsttxid\" : \"hash\", (string) the first transaction of the stream.\n" + " \"firstblockheight\" : \"n\", (numeric) the block the stream starts in.\n" + " \"firstdeqid\" : n, (numeric) The sequence id of the first data chunk in this block\n" + " \"lastseqid\" : n, (numeric) The sequence id of the last data chunk in this block\n" + + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09 false\"") + + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleCli("getblock", "12800") + + HelpExampleRpc("getblock", "12800 false") + ); + + LOCK(cs_main); + + std::string strHash = params[0].get_str(); + bool fVerbose = true; + if (params.size() > 1) { + std::string verboseflag = params[1].get_str(); + if ( verboseflag == "false" ) + fVerbose = false; + } + + // If height is supplied, find the hash + if (strHash.size() < (2 * sizeof(uint256))) { + // std::stoi allows characters, whereas we want to be strict + regex r("[[:digit:]]+"); + if (!regex_match(strHash, r)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); + } + + int nHeight = -1; + try { + nHeight = std::stoi(strHash); + } + catch (const std::exception &e) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); + } + + if (nHeight < 0 || nHeight > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + } + strHash = chainActive[nHeight]->GetBlockHash().GetHex(); + } + + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex,1)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + UniValue result(UniValue::VOBJ); + int firstseqid = 0; + int lastseqid = 0; + int i = 0; + int did1 = 0; + int skippedtxs = 0; + int failed = 0; + int getfirstblock = 0; + static std::string streamid,firsttxid; + static int firsttxnHeight; + std::string blockdata; + fprintf(stderr, "number of tx in block: %ld\n", block.vtx.size()); + // Iif block tx size is > 2 then we can do this + if ( block.vtx.size() > 2 ) + { + BOOST_FOREACH(const CTransaction&tx, block.vtx) + { + // ignore first and last TX and any TX that does not have 3 vouts. + if ( (i == 0) || (i == (block.vtx.size() -1)) || (tx.vout.size() != 3) ) + { + fprintf(stderr, "skipped tx number: %d\n",i); + skippedtxs = skippedtxs + 1; + } else { + std::string opretstr = HexStr(tx.vout[2].scriptPubKey.begin(), tx.vout[2].scriptPubKey.end()); + // scriptPubKey is longer than 81, should mean its an OP_RETURN, maybe also check vout == 0 ? + if ( opretstr.size() > 81 ) { + std::string idstr = opretstr.substr (8,64); // stream ID or txid + std::string seqidstr = opretstr.substr (72,8); // sequence ID + std::string data = opretstr.substr (80); // data chunk + unsigned int seqid; + std::stringstream ss; + ss << std::hex << seqidstr; + ss >> seqid; + if ( seqid == 1 ) { + streamid = idstr; + getfirstblock = 1; + } else if ( seqid == 2 ) { + firsttxid = idstr; + } else if (firsttxid.empty()) { + firsttxid.append(idstr); + } else if ( firsttxid != idstr ) { + printf("firsttxid.%s idstr.%s change firsttxid and wipe streamid?\n",firsttxid.c_str(),idstr.c_str()); + firsttxid.clear(); + firsttxid.append(idstr); + streamid.clear(); + firsttxnHeight = 0; + } + if ( seqid == (lastseqid + 1) || did1 == 0 ) { + blockdata.append(data); + } else { + result.push_back(Pair("error","chunck out of order or missing in this block!")); + result.push_back(Pair("lastvalidseqid", (int)lastseqid)); + break; + } + if ( did1 == 0 ) { + firstseqid = seqid; + did1 = 1; + } + lastseqid = seqid; + } else { + skippedtxs = skippedtxs + 1; + fprintf(stderr, "skipped tx number: %d\n",i); + } + // function here to extract seqid from first and last TX + // we an push the data or not depending on input from RPC. + } + i = i + 1; + } + if (streamid.empty() || getfirstblock == 1) { + if ( lastseqid == 1) { + firsttxid = block.vtx[1].GetHash().GetHex(); + } + uint256 hash; CTransaction firsttx; + uint256 firsttxid_256(uint256S(firsttxid)); + if (GetTransaction(firsttxid_256,firsttx,hash,false)) { + if ( streamid.empty() ) { + std::string firststreamid = HexStr(firsttx.vout[2].scriptPubKey.begin(), firsttx.vout[2].scriptPubKey.end()); + streamid.append(firststreamid.substr (8,64)); + } + printf("first stream id changed to: %s\n", streamid.c_str()); + BlockMap::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end() && (*mi).second) { + CBlockIndex* pindex = (*mi).second; + printf("found block height: %d\n",pindex->nHeight); + if (chainActive.Contains(pindex)) { + firsttxnHeight = pindex->nHeight; + } + } + } + } + } else { + failed = 1; + } + + if ( failed == 1 || skippedtxs == i ) { + result.push_back(Pair("error","there is no data in this block.")); + } else { + std::string decodedstreamid; + hex2ascii(streamid, decodedstreamid); + result.push_back(Pair("streamid", decodedstreamid.c_str())); + result.push_back(Pair("firsttxid", firsttxid)); + result.push_back(Pair("firstblockheight", (int)firsttxnHeight)); + result.push_back(Pair("firstseqid", (int)firstseqid)); + result.push_back(Pair("lastseqid", (int)lastseqid)); + if (fVerbose == true) { + result.push_back(Pair("data", blockdata)); + } + } + return result; +} + UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) { UniValue result(UniValue::VOBJ); @@ -816,7 +1028,7 @@ UniValue kvsearch(const UniValue& params, bool fHelp) " \"currentheight\": xxxxx, (numeric) current height of the chain\n" " \"key\": \"xxxxx\", (string) key\n" " \"keylen\": xxxxx, (string) length of the key \n" - " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" + " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" " \"height\": xxxxx, (numeric) height the key was stored at\n" " \"expiration\": xxxxx, (numeric) height the key will expire\n" " \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n" diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index f724b5071..653c786fe 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -285,6 +285,7 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "getbestblockhash", &getbestblockhash, true }, { "blockchain", "getblockcount", &getblockcount, true }, { "blockchain", "getblock", &getblock, true }, + { "blockchain", "getdatafromblock", &getdatafromblock, true }, { "blockchain", "getblockdeltas", &getblockdeltas, false }, { "blockchain", "getblockhashes", &getblockhashes, true }, { "blockchain", "getblockhash", &getblockhash, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 98c3357f9..81ca8a8b9 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -364,6 +364,7 @@ extern UniValue getblockdeltas(const UniValue& params, bool fHelp); extern UniValue getblockhash(const UniValue& params, bool fHelp); extern UniValue getblockheader(const UniValue& params, bool fHelp); extern UniValue getblock(const UniValue& params, bool fHelp); +extern UniValue getdatafromblock(const UniValue& params, bool fHelp); extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp); extern UniValue gettxout(const UniValue& params, bool fHelp); extern UniValue verifychain(const UniValue& params, bool fHelp); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3f42fb241..3a78574d9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -44,6 +44,8 @@ using namespace std; using namespace libzcash; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; +extern int32_t ASSETCHAINS_STREAM; extern UniValue TxJoinSplitToJSON(const CTransaction& tx); extern uint8_t ASSETCHAINS_PRIVATE; uint32_t komodo_segid32(char *coinaddr); @@ -4606,8 +4608,8 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33) // ((uint8_t *)&revtxid)[i] = ((uint8_t *)&utxotxid)[31 - i]; txNew.vin[0].prevout.hash = utxotxid; //revtxid; txNew.vin[0].prevout.n = utxovout; - txNew.vout[0].scriptPubKey = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG; txNew.vout[0].nValue = utxovalue - txfee; + txNew.vout[0].scriptPubKey = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG; CTransaction txNewConst(txNew); signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, utxovalue, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); if (!signSuccess)