diff --git a/src/chainparams.cpp b/src/chainparams.cpp index c0e1bf92f..be9d7ac8a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -244,13 +244,13 @@ void *chainparams_commandline(void *ptr) if (ASSETCHAINS_LWMAPOS != 0) { mainParams.consensus.posLimit = uint256S("000000000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); - mainParams.consensus.nPOSAveragingWindow = 100; + mainParams.consensus.nPOSAveragingWindow = 45; // spacing is 1000 units per block to get better resolution, POS is 50% hard coded for now, we can vary it later // when we get reliable integer math on nLwmaPOSAjustedWeight mainParams.consensus.nPOSTargetSpacing = VERUS_BLOCK_POSUNITS * 2; // nLwmaPOSAjustedWeight = (N+1)/2 * (0.9989^(500/nPOSAveragingWindow)) * nPOSTargetSpacing // this needs to be recalculated if VERUS_BLOCK_POSUNITS is changed - mainParams.consensus.nLwmaPOSAjustedWeight = 100446; + mainParams.consensus.nLwmaPOSAjustedWeight = 45000; } checkpointData = //(Checkpoints::CCheckpointData) diff --git a/src/crypto/verus_hash.h b/src/crypto/verus_hash.h index 394a5e070..1d9b0b4c7 100644 --- a/src/crypto/verus_hash.h +++ b/src/crypto/verus_hash.h @@ -31,7 +31,6 @@ class CVerusHash result = buf2; curPos = 0; std::fill(buf1, buf1 + sizeof(buf1), 0); - std::fill(buf2, buf2 + sizeof(buf2), 0); } void Finalize(unsigned char hash[32]) @@ -42,7 +41,7 @@ class CVerusHash haraka512(hash, curBuf); } else - std::memcpy(hash, result, 32); + std::memcpy(hash, curBuf, 32); } private: diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 7be8c749f..d42a8f9e6 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1266,11 +1266,13 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) int32_t txn_count; uint32_t voutNum; bool isPOS = false; - CTxDestination voutaddress; + CTxDestination voutaddress, destaddress; arith_uint256 target, hash; CTransaction tx; - // TODO(miketout) must initialize destaddr properly + if (!pblock->isVerusPOSBlock()) + return false; + char voutaddr[64],destaddr[64]; target.SetCompact(pblock->GetVerusPOSTarget()); @@ -1295,7 +1297,7 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) } else { - hash = UintToArith256(tx.GetVerusPOSHash(voutNum, height, pastBlockIndex->GetBlockHash())) / tx.vout[voutNum].nValue; + hash = UintToArith256(tx.GetVerusPOSHash(voutNum, height, pastBlockIndex->GetBlockHash())); if (hash <= target) { if ((mapBlockIndex.count(blkHash) == 0) || @@ -1316,13 +1318,16 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height) { arith_uint256 cTarget; cTarget.SetCompact(lwmaGetNextPOSRequired(previndex, Params().GetConsensus())); + if (cTarget != target) { fprintf(stderr,"ERROR: invalid PoS block %s - invalid diff target\n",blkHash.ToString().c_str()); } - else if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) ) + else if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) && + ExtractDestination(tx.vout[voutNum].scriptPubKey, destaddress) ) { strcpy(voutaddr, CBitcoinAddress(voutaddress).ToString().c_str()); + strcpy(destaddr, CBitcoinAddress(destaddress).ToString().c_str()); if ( strcmp(destaddr,voutaddr) == 0 ) { isPOS = true; diff --git a/src/komodo_globals.h b/src/komodo_globals.h index a2d342d9f..8663a0c0a 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -80,8 +80,8 @@ uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH; // Verus proof of stake controls int32_t ASSETCHAINS_LWMAPOS = 0; // percentage of blocks should be PoS -int32_t VERUS_BLOCK_POSUNITS = 1000; // one block is 1000 units -int32_t VERUS_MIN_STAKEAGE = 200; // 1/2 this should also be a cap on the POS averaging window, or startup could be too easy +int32_t VERUS_BLOCK_POSUNITS = 1000; // one block is 1000 units +int32_t VERUS_MIN_STAKEAGE = 150; // 1/2 this should also be a cap on the POS averaging window, or startup could be too easy uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; diff --git a/src/miner.cpp b/src/miner.cpp index 5a576f069..22d5d5a5b 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -111,7 +111,7 @@ extern int32_t ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOS extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED; extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[]; extern const char *ASSETCHAINS_ALGORITHMS[]; -extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; +extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[]; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; @@ -462,6 +462,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) arith_uint256 posHash; siglen = verus_staked(key, txStaked, nBitsPOS, posHash, utxosig); blocktime = GetAdjustedTime(); + pblock->SetVerusPOSTarget(nBitsPOS); } else { @@ -530,13 +531,17 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; - // Randomise nonce - arith_uint256 nonce = UintToArith256(GetRandHash()); + // if not Verus stake, setup nonce, otherwise, leave it alone + if (!isStake || ASSETCHAINS_LWMAPOS == 0) + { + // Randomise nonce + arith_uint256 nonce = UintToArith256(GetRandHash()); - // Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters) - nonce <<= ASSETCHAINS_NONCESHIFT[ASSETCHAINS_ALGO]; - nonce >>= 16; - pblock->nNonce = ArithToUint256(nonce); + // Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters) + nonce <<= ASSETCHAINS_NONCESHIFT[ASSETCHAINS_ALGO]; + nonce >>= 16; + pblock->nNonce = ArithToUint256(nonce); + } // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); @@ -544,7 +549,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) if ( ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || NOTARY_PUBKEY33[0] == 0 ) { UpdateTime(pblock, Params().GetConsensus(), pindexPrev); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); } pblock->nSolution.clear(); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); @@ -580,7 +585,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, bool isStake) } } } - return pblocktemplate.release(); } @@ -816,22 +820,23 @@ void static VerusStaker(CWallet *pwallet) // try a nice clean peer connection to start waitForPeers(chainparams); sleep(5); - CBlockIndex* curTip; + CBlockIndex *curTip = chainActive.Tip(), *lastTip; do { + lastTip = curTip; + printf("Verifying block height %d \n", lastTip->nHeight); + MilliSleep(3000 + rand() % 1900); curTip = chainActive.Tip(); - printf("Verifying block height %d \n", chainActive.Tip()->nHeight); - MilliSleep(2000 + rand() % 1900); - } while (curTip != chainActive.Tip()); + } while (curTip != lastTip); SetThreadPriority(THREAD_PRIORITY_LOWEST); sleep(5); - printf("Staking height %d\n", chainActive.Tip()->nHeight + 1); + printf("Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL); + //fprintf(stderr,"Staking height %d for %s\n", chainActive.Tip()->nHeight + 1, ASSETCHAINS_SYMBOL); miningTimer.start(); try { - fprintf(stderr,"Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); while (true) { miningTimer.stop(); @@ -847,13 +852,19 @@ void static VerusStaker(CWallet *pwallet) Mining_start = (uint32_t)time(NULL); } + // Check for stop or if block needs to be rebuilt + boost::this_thread::interruption_point(); + // try to stake a block - CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, true); + CBlockTemplate *ptr = NULL; + if (Mining_height > VERUS_MIN_STAKEAGE) + ptr = CreateNewBlockWithKey(reservekey, true); if ( ptr == 0 ) { - // wait to try another staking block - sleep(5); + // wait to try another staking block until after the tip moves again + while ( chainActive.Tip() == pindexPrev ) + sleep(5); continue; } @@ -861,44 +872,43 @@ void static VerusStaker(CWallet *pwallet) if (!pblocktemplate.get()) { if (GetArg("-mineraddress", "").empty()) { - LogPrintf("Error in %s miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n", + LogPrintf("Error in %s staker: Keypool ran out, please call keypoolrefill before restarting the mining thread\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); } else { // Should never reach here, because -mineraddress validity is checked in init.cpp - LogPrintf("Error in %s miner: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL); + LogPrintf("Error in %s staker: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL); } return; } + CBlock *pblock = &pblocktemplate->block; - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA ) - { - if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && 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); - } - } - IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); - LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], - pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION)); + LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION)); // // Search // - uint32_t savebits; int64_t nStart = GetTime(); + int64_t nStart = GetTime(); + + // we don't use this, but IncrementExtraNonce is the function that builds the merkle tree + unsigned int nExtraNonce = 0; + IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); pblock->nSolution = solnPlaceholder; - savebits = pblock->nBits; - arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - arith_uint256 mask(ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO]); - Mining_start = 0; + if (vNodes.empty() && chainparams.MiningRequiresPeers()) + { + if ( Mining_height > ASSETCHAINS_MINHEIGHT ) + { + fprintf(stderr,"no nodes, attempting reconnect\n"); + continue; + } + } + + if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) + { + fprintf(stderr,"timeout, retrying\n"); + continue; + } if ( pindexPrev != chainActive.Tip() ) { @@ -907,91 +917,37 @@ void static VerusStaker(CWallet *pwallet) continue; } - int32_t percPoS,z; + SetThreadPriority(THREAD_PRIORITY_NORMAL); - while (true) - { - // for speed check multiples at a time - for (int i = 0; i < ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO]; i++) - { - solutionTargetChecks.increment(); + int32_t unlockTime = komodo_block_unlocktime(Mining_height); + int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue); - // Update nNonce and nTime - pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); + uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits)); - if ( UintToArith256(pblock->GetHash()) <= hashTarget ) - { - SetThreadPriority(THREAD_PRIORITY_NORMAL); + LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); + LogPrintf("Staked block found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); + printf("Found block %d \n", Mining_height ); + printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL); + printf(" hash: %s \ntarget: %s\n", pblock->GetHash().GetHex().c_str(), hashTarget.GetHex().c_str()); + if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE) + printf("- timelocked until block %i\n", unlockTime); + else + printf("\n"); - int32_t unlockTime = komodo_block_unlocktime(Mining_height); - int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); - LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]); - LogPrintf("Staked block found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); - printf("Found block %d \n", Mining_height ); - printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL); - printf(" hash: %s \ntarget: %s\n", pblock->GetHash().GetHex().c_str(), hashTarget.GetHex().c_str()); - if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE) - printf("- timelocked until block %i\n", unlockTime); - else - printf("\n"); + UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - ProcessBlockFound(pblock, *pwallet, reservekey); + ProcessBlockFound(pblock, *pwallet, reservekey); - SetThreadPriority(THREAD_PRIORITY_LOWEST); + sleep(3); + // Check for stop or if block needs to be rebuilt + boost::this_thread::interruption_point(); + SetThreadPriority(THREAD_PRIORITY_LOWEST); - // In regression test mode, stop mining after a block is found. - if (chainparams.MineBlocksOnDemand()) { - throw boost::thread_interrupted(); - } - break; - } - else - { - if ((UintToArith256(pblock->nNonce) & mask) == mask) - { - break; - } - } - } - - // Check for stop or if block needs to be rebuilt - boost::this_thread::interruption_point(); - - if (vNodes.empty() && chainparams.MiningRequiresPeers()) - { - if ( Mining_height > ASSETCHAINS_MINHEIGHT ) - { - fprintf(stderr,"no nodes, attempting reconnect\n"); - break; - } - } - - if ((UintToArith256(pblock->nNonce) & mask) == mask) - { - fprintf(stderr,"%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576); - break; - } - - if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60) - { - fprintf(stderr,"timeout, retrying\n"); - break; - } - - if ( pindexPrev != chainActive.Tip() ) - { - printf("Block %d added to chain\n", chainActive.Tip()->nHeight); - break; - } - - pblock->nBits = savebits; - UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) - { - // Changing pblock->nTime can change work required on testnet: - hashTarget.SetCompact(pblock->nBits); - } + // In regression test mode, stop mining after a block is found. + if (chainparams.MineBlocksOnDemand()) { + throw boost::thread_interrupted(); } } } @@ -1040,12 +996,13 @@ void static BitcoinMiner_noeq() // try a nice clean peer connection to start waitForPeers(chainparams); sleep(5); - CBlockIndex* curTip; + CBlockIndex *curTip = chainActive.Tip(), *lastTip; do { + lastTip = curTip; + printf("Verifying block height %d \n", lastTip->nHeight); + MilliSleep(3000 + rand() % 1900); curTip = chainActive.Tip(); - printf("Verifying block height %d \n", chainActive.Tip()->nHeight); - MilliSleep(2000 + rand() % 1900); - } while (curTip != chainActive.Tip()); + } while (curTip != lastTip); SetThreadPriority(THREAD_PRIORITY_LOWEST); diff --git a/src/primitives/block.h b/src/primitives/block.h index d43bd18d9..8dbcd7d5d 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -96,8 +96,8 @@ public: for (const unsigned char *p = nNonce.begin() + 3; p >= nNonce.begin(); p--) { - nBits += *p; nBits <<= 8; + nBits += *p; } return nBits; } @@ -122,6 +122,7 @@ public: tmpNonce = ((arNonce << 128) >> 128); hashWriter << ArithToUint256(tmpNonce); + nNonce = ArithToUint256(UintToArith256(hashWriter.GetHash()) << 128 | tmpNonce); } }; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 41e6454f4..d6d7051cf 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -11,6 +11,7 @@ #include "script/script.h" #include "serialize.h" #include "uint256.h" +#include "arith_uint256.h" #include "consensus/consensus.h" #include "hash.h" @@ -489,9 +490,9 @@ public: { uint256 txid = GetHash(); if (voutNum >= vout.size()) - return uint256(); + return uint256S("ff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"); - return _GetVerusPOSHash(txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue); + return ArithToUint256(UintToArith256(_GetVerusPOSHash(txid, voutNum, height, pastHash, (uint64_t)vout[voutNum].nValue)) / vout[voutNum].nValue); } std::string ToString() const; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 009684db6..49ea9270d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4663,5 +4663,5 @@ int32_t komodo_staked(CPubKey &pubkey, CMutableTransaction &txNew,uint32_t nBits int32_t verus_staked(CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig) { - return pwalletMain->VerusStakeTransaction(pubkey, txNew, nBits, hashResult, utxosig); + return pwalletMain->VerusStakeTransaction(txNew, nBits, hashResult, utxosig); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 02a31b916..c3451afc0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -21,6 +21,7 @@ #include "zcash/Note.hpp" #include "crypter.h" #include "coins.h" + #include #include @@ -43,6 +44,7 @@ bool fPayAtLeastCustomFee = true; extern int32_t KOMODO_EXCHANGEWALLET; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; +extern int32_t VERUS_MIN_STAKEAGE; CBlockIndex *komodo_chainactive(int32_t height); /** @@ -1002,6 +1004,8 @@ bool CWallet::VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &st vector vecOutputs; COutput *pwinner = NULL; CBlockIndex *pastBlockIndex; + txnouttype whichType; + std:vector> vSolutions; pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false); @@ -1011,11 +1015,11 @@ bool CWallet::VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &st BOOST_FOREACH(COutput &txout, vecOutputs) { - if ((curHash = UintToArith256(txout.tx->GetVerusPOSHash(txout.i, nHeight, pastHash)) / txout.tx->vout[txout.i].nValue) <= target && - txout.fSpendable) + if (txout.fSpendable && (UintToArith256(txout.tx->GetVerusPOSHash(txout.i, nHeight, pastHash)) <= target) && (txout.nDepth >= VERUS_MIN_STAKEAGE)) { // get the smallest winner - if (!pwinner || pwinner->tx->vout[pwinner->i].nValue > txout.tx->vout[txout.i].nValue) + if (Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH) && + (!pwinner || pwinner->tx->vout[pwinner->i].nValue > txout.tx->vout[txout.i].nValue)) pwinner = &txout; } } @@ -1029,18 +1033,21 @@ bool CWallet::VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &st return false; } -int32_t CWallet::VerusStakeTransaction(CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const +int32_t CWallet::VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const { arith_uint256 target; CTransaction stakeSource; int32_t voutNum, siglen = 0; int64_t nValue; + txnouttype whichType; + std::vector> vSolutions; CBlockIndex *tipindex = chainActive.Tip(); bnTarget = lwmaGetNextPOSRequired(tipindex, Params().GetConsensus()); target.SetCompact(bnTarget); - if (!VerusSelectStakeOutput(hashResult, stakeSource, voutNum, tipindex->nHeight, target)) + if (!VerusSelectStakeOutput(hashResult, stakeSource, voutNum, tipindex->nHeight + 1, target) || + !Solver(stakeSource.vout[voutNum].scriptPubKey, whichType, vSolutions)) { return 0; } @@ -1058,20 +1065,16 @@ int32_t CWallet::VerusStakeTransaction(CPubKey &pubkey, CMutableTransaction &txN txNew.vin[0].prevout.hash = stakeSource.GetHash(); txNew.vin[0].prevout.n = voutNum; - /* - uint8_t *script; - int32_t i; - uint8_t *ptr; - - txNew.vout[0].scriptPubKey.resize(35); - ptr = (uint8_t *)pubkey.begin(); - script = (uint8_t *)(txNew.vout[0].scriptPubKey.data()); - script[0] = 33; - for (i=0; i<33; i++) - script[i+1] = ptr[i]; - script[34] = OP_CHECKSIG; - */ - txNew.vout[0].scriptPubKey << ToByteVector(pubkey) << OP_CHECKSIG; + if (whichType == TX_PUBKEY) + { + txNew.vout[0].scriptPubKey << ToByteVector(vSolutions[0]) << OP_CHECKSIG; + } + else if (whichType == TX_PUBKEYHASH) + { + txNew.vout[0].scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(vSolutions[0]) << OP_EQUALVERIFY << OP_CHECKSIG; + } + else + return 0; nValue = txNew.vout[0].nValue = voutNum - txfee; txNew.nLockTime = 0; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 8af9243ee..0df2cd4dc 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1150,7 +1150,7 @@ public: // staking functions bool VerusSelectStakeOutput(arith_uint256 &hashResult, CTransaction &stakeSource, int32_t &voutNum, int32_t nHeight, const arith_uint256 &target) const; - int32_t VerusStakeTransaction(CPubKey &pubkey, CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const; + int32_t VerusStakeTransaction(CMutableTransaction &txNew, uint32_t &bnTarget, arith_uint256 &hashResult, uint8_t *utxosig) const; }; /** A key allocated from the key pool. */