Merge #10581: Simplify return values of GetCoin/HaveCoin(InCache)

21180ff Simplify return values of GetCoin/HaveCoin(InCache) (Pieter Wuille)

Tree-SHA512: eae0aa64fa1308191100cdc7cdc790c825f33b066c200a18b5895d7d5806cee1cc4caba1766ef3379a7cf93dde4bbae2bc9be92947935f5741f5c126d3ee991b
This commit is contained in:
Wladimir J. van der Laan 2017-06-27 08:49:44 +02:00 committed by Alexander Block
parent 06aa02ff63
commit 549839a504
5 changed files with 28 additions and 19 deletions

View File

@ -11,11 +11,15 @@
#include <assert.h> #include <assert.h>
bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; } bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(); } uint256 CCoinsView::GetBestBlock() const { return uint256(); }
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; } bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
CCoinsViewCursor *CCoinsView::Cursor() const { return 0; } CCoinsViewCursor *CCoinsView::Cursor() const { return 0; }
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
{
Coin coin;
return GetCoin(outpoint, coin);
}
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { } CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
bool CCoinsViewBacked::GetCoin(const COutPoint &outpoint, Coin &coin) const { return base->GetCoin(outpoint, coin); } bool CCoinsViewBacked::GetCoin(const COutPoint &outpoint, Coin &coin) const { return base->GetCoin(outpoint, coin); }
@ -55,7 +59,7 @@ bool CCoinsViewCache::GetCoin(const COutPoint &outpoint, Coin &coin) const {
CCoinsMap::const_iterator it = FetchCoin(outpoint); CCoinsMap::const_iterator it = FetchCoin(outpoint);
if (it != cacheCoins.end()) { if (it != cacheCoins.end()) {
coin = it->second.coin; coin = it->second.coin;
return true; return !coin.IsSpent();
} }
return false; return false;
} }

View File

@ -146,11 +146,13 @@ private:
class CCoinsView class CCoinsView
{ {
public: public:
//! Retrieve the Coin (unspent transaction output) for a given outpoint. /** Retrieve the Coin (unspent transaction output) for a given outpoint.
* Returns true only when an unspent coin was found, which is returned in coin.
* When false is returned, coin's value is unspecified.
*/
virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const; virtual bool GetCoin(const COutPoint &outpoint, Coin &coin) const;
//! Just check whether we have data for a given outpoint. //! Just check whether a given outpoint is unspent.
//! This may (but cannot always) return true for spent outputs.
virtual bool HaveCoin(const COutPoint &outpoint) const; virtual bool HaveCoin(const COutPoint &outpoint) const;
//! Retrieve the block hash whose state this CCoinsView currently represents //! Retrieve the block hash whose state this CCoinsView currently represents

View File

@ -51,12 +51,6 @@ public:
return true; return true;
} }
bool HaveCoin(const COutPoint& outpoint) const override
{
Coin coin;
return GetCoin(outpoint, coin);
}
uint256 GetBestBlock() const override { return hashBestBlock_; } uint256 GetBestBlock() const override { return hashBestBlock_; }
bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) override bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) override
@ -148,8 +142,22 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
{ {
uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration. uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration.
Coin& coin = result[COutPoint(txid, 0)]; Coin& coin = result[COutPoint(txid, 0)];
// Determine whether to test HaveCoin before or after Access* (or both). As these functions
// can influence each other's behaviour by pulling things into the cache, all combinations
// are tested.
bool test_havecoin_before = (insecure_rand() & 0x3) == 0; // TODO change to InsecureRandBits(2) when backporting Bitcoin #10321
bool test_havecoin_after = (insecure_rand() & 0x3) == 0; // TODO change to InsecureRandBits(2) when backporting Bitcoin #10321
bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false;
const Coin& entry = (insecure_rand() % 500 == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); const Coin& entry = (insecure_rand() % 500 == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
BOOST_CHECK(coin == entry); BOOST_CHECK(coin == entry);
BOOST_CHECK(!test_havecoin_before || result_havecoin == !entry.IsSpent());
if (test_havecoin_after) {
bool ret = stack.back()->HaveCoin(COutPoint(txid, 0));
BOOST_CHECK(ret == !entry.IsSpent());
}
if (insecure_rand() % 5 == 0 || coin.IsSpent()) { if (insecure_rand() % 5 == 0 || coin.IsSpent()) {
Coin newcoin; Coin newcoin;
@ -631,7 +639,7 @@ BOOST_AUTO_TEST_CASE(ccoins_access)
CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH ); CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH );
CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY ); CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY );
CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH); CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
CheckAccessCoin(PRUNED, ABSENT, PRUNED, NO_ENTRY , FRESH ); CheckAccessCoin(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 ); CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 );
CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH ); CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH );
CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY ); CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );

View File

@ -988,11 +988,7 @@ bool CCoinsViewMemPool::GetCoin(const COutPoint &outpoint, Coin &coin) const {
return false; return false;
} }
} }
return (base->GetCoin(outpoint, coin) && !coin.IsSpent()); return base->GetCoin(outpoint, coin);
}
bool CCoinsViewMemPool::HaveCoin(const COutPoint &outpoint) const {
return mempool.exists(outpoint) || base->HaveCoin(outpoint);
} }
size_t CTxMemPool::DynamicMemoryUsage() const { size_t CTxMemPool::DynamicMemoryUsage() const {

View File

@ -663,8 +663,7 @@ protected:
public: public:
CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn); CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn);
bool GetCoin(const COutPoint &outpoint, Coin &coin) const; bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
bool HaveCoin(const COutPoint &outpoint) const;
}; };
// We want to sort transactions by coin age priority // We want to sort transactions by coin age priority