From c1e0fac4f81eb92ecf8fe98bf8aad0c78ac69564 Mon Sep 17 00:00:00 2001 From: janko33bd Date: Tue, 30 Jan 2018 23:52:33 +0100 Subject: [PATCH] added stake cache + checked ismine --- src/pos.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++ src/pos.h | 11 ++++++++ src/script/ismine.cpp | 5 +++- src/wallet/wallet.cpp | 44 +++++++++++++------------------- src/wallet/wallet.h | 2 +- 5 files changed, 92 insertions(+), 29 deletions(-) diff --git a/src/pos.cpp b/src/pos.cpp index 55957b7db..4c9a4fb70 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -154,3 +154,62 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig return VerifyScript(txin.scriptSig, txout.scriptPubKey, flags, TransactionSignatureChecker(&txTo, nIn), NULL); } + +bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTimeBlock, const COutPoint& prevout, uint32_t* pBlockTime){ + std::map tmp; + return CheckKernel(pindexPrev, nBits, nTimeBlock, prevout, pBlockTime, tmp); +} + +bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTime, const COutPoint& prevout, uint32_t* pBlockTime, const std::map& cache) +{ + uint256 hashProofOfStake, targetProofOfStake; + auto it=cache.find(prevout); + + if(it == cache.end()) { + CTransaction txPrev; + CDiskTxPos txindex; + if (!ReadFromDisk(txPrev, txindex, *pblocktree, prevout)) + return false; + + // Read block header + CBlock block; + const CDiskBlockPos& pos = CDiskBlockPos(txindex.nFile, txindex.nPos); + if (!ReadBlockFromDisk(block, pos, Params().GetConsensus())) + return false; + + int nDepth; + if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetConsensus().nStakeMinConfirmations - 1, nDepth)) + return false; + + if (pBlockTime) + *pBlockTime = block.GetBlockTime(); + + return CheckStakeKernelHash(pindexPrev, nBits, new CCoins(txPrev, pindexPrev->nHeight), prevout, nTime); + }else{ + //found in cache + const CStakeCache& stake = it->second; + if (pBlockTime) + *pBlockTime = stake.blockFrom.GetBlockTime(); + return CheckStakeKernelHash(pindexPrev, nBits, new CCoins(stake.txPrev, pindexPrev->nHeight), prevout, nTime); + } + +} + +void CacheKernel(std::map& cache, const COutPoint& prevout){ + if(cache.find(prevout) != cache.end()){ + //already in cache + return; + } + CTransaction txPrev; + CDiskTxPos txindex; + if (!ReadFromDisk(txPrev, txindex, *pblocktree, prevout)) + return; + // Read block + CBlock block; + const CDiskBlockPos& pos = CDiskBlockPos(txindex.nFile, txindex.nPos); + if (!ReadBlockFromDisk(block, pos, Params().GetConsensus())) + return; + CStakeCache c(block, txindex, txPrev); + cache.insert({prevout, c}); +} + diff --git a/src/pos.h b/src/pos.h index 827c85bae..85a1c0034 100644 --- a/src/pos.h +++ b/src/pos.h @@ -21,11 +21,22 @@ using namespace std; /** Compute the hash modifier for proof-of-stake */ uint256 ComputeStakeModifier(const CBlockIndex* pindexPrev, const uint256& kernel); +struct CStakeCache{ + CStakeCache(CBlockHeader blockFrom_, CDiskTxPos txindex_, const CTransaction txPrev_) : blockFrom(blockFrom_), txindex(txindex_), txPrev(txPrev_){ + } + CBlockHeader blockFrom; + CDiskTxPos txindex; + const CTransaction txPrev; +}; + // Check whether the coinstake timestamp meets protocol bool CheckCoinStakeTimestamp(int64_t nTimeBlock, int64_t nTimeTx); bool CheckStakeBlockTimestamp(int64_t nTimeBlock); +bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTime, const COutPoint& prevout, uint32_t* pBlockTime = NULL); +bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTime, const COutPoint& prevout, uint32_t* pBlockTime, const std::map& cache); bool CheckStakeKernelHash(const CBlockIndex* pindexPrev, unsigned int nBits, const CCoins* txPrev, const COutPoint& prevout, unsigned int nTimeTx); bool IsConfirmedInNPrevBlocks(const CDiskTxPos& txindex, const CBlockIndex* pindexFrom, int nMaxDepth, int& nActualDepth); bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, CValidationState &state); +void CacheKernel(std::map& cache, const COutPoint& prevout); bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType); #endif // BLACKCOIN_POS_H diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index 535c56b57..58fa316f2 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -67,7 +67,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { isminetype ret = IsMine(keystore, subscript); - if (ret == ISMINE_SPENDABLE) + if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || ret == ISMINE_NO) return ret; } break; @@ -84,6 +84,9 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) return ISMINE_SPENDABLE; break; } + + default: + break; } if (keystore.HaveWatchOnly(scriptPubKey)) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0f75bb065..c7a8a79c7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -661,31 +661,6 @@ bool CWallet::SelectCoinsForStaking(CAmount& nTargetValue, std::setnHeight), prevout, nTime); -} - // miner's coin stake reward int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees) { @@ -735,6 +710,21 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int if (setCoins.empty()) return false; + static std::map stakeCache; + if(stakeCache.size() > setCoins.size() + 100){ + //Determining if the cache is still valid is harder than just clearing it when it gets too big, so instead just clear it + //when it has more than 100 entries more than the actual setCoins. + stakeCache.clear(); + } + if(GetBoolArg("-stakecache", DEFAULT_STAKE_CACHE)) { + BOOST_FOREACH(const PAIRTYPE(const CWalletTx*, unsigned int)& pcoin, setCoins) + { + boost::this_thread::interruption_point(); + COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second); + CacheKernel(stakeCache, prevoutStake); //this will do a 2 disk loads per op + } + + } int64_t nCredit = 0; CScript scriptPubKeyKernel; @@ -748,9 +738,9 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int // Search backward in time from the given txNew timestamp // Search nSearchInterval seconds back up to nMaxStakeSearchInterval COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second); - int64_t nBlockTime; + uint32_t nBlockTime; //LogPrintf("looking for coinstake \n"); - if (CheckKernel(pindexPrev, nBits, txNew.nTime - n, prevoutStake, &nBlockTime)) + if (CheckKernel(pindexPrev, nBits, txNew.nTime - n, prevoutStake, &nBlockTime, stakeCache)) { // Found a kernel LogPrint("coinstake", "CreateCoinStake : kernel found\n"); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 140277c68..743e3c5f7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -932,6 +932,7 @@ public: /* Set the current HD master key (will reset the chain child index counters) */ bool SetHDMasterKey(const CPubKey& key); + static const bool DEFAULT_STAKE_CACHE = true; }; /** A key allocated from the key pool. */ @@ -989,5 +990,4 @@ public: } }; -bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, int64_t nTime, const COutPoint& prevout, int64_t* pBlockTime = NULL); #endif // BITCOIN_WALLET_WALLET_H