mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-16 02:27:43 +02:00
coins: make CCoinsView methods pure virtual
`CCoinsView` provided default no-op implementations, which allowed constructing a bare view and silently getting dummy behavior. Make all interface methods pure virtual and remove the legacy default definitions from `coins.cpp` so callers must choose an explicit implementation. Move the virtual destructor to the beginning to avoid mixing it between the methods. No-op backing behavior remains available via `CoinsViewEmpty`.
This commit is contained in:
@@ -14,22 +14,6 @@ TRACEPOINT_SEMAPHORE(utxocache, add);
|
||||
TRACEPOINT_SEMAPHORE(utxocache, spent);
|
||||
TRACEPOINT_SEMAPHORE(utxocache, uncache);
|
||||
|
||||
std::optional<Coin> CCoinsView::GetCoin(const COutPoint& outpoint) const { return std::nullopt; }
|
||||
std::optional<Coin> CCoinsView::PeekCoin(const COutPoint& outpoint) const { return GetCoin(outpoint); }
|
||||
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
||||
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
|
||||
void CCoinsView::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash)
|
||||
{
|
||||
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { }
|
||||
}
|
||||
|
||||
std::unique_ptr<CCoinsViewCursor> CCoinsView::Cursor() const { return nullptr; }
|
||||
|
||||
bool CCoinsView::HaveCoin(const COutPoint& outpoint) const
|
||||
{
|
||||
return GetCoin(outpoint).has_value();
|
||||
}
|
||||
|
||||
CCoinsViewBacked::CCoinsViewBacked(CCoinsView* in_view) : base(in_view) { }
|
||||
std::optional<Coin> CCoinsViewBacked::GetCoin(const COutPoint& outpoint) const { return base->GetCoin(outpoint); }
|
||||
std::optional<Coin> CCoinsViewBacked::PeekCoin(const COutPoint& outpoint) const { return base->PeekCoin(outpoint); }
|
||||
|
||||
40
src/coins.h
40
src/coins.h
@@ -303,43 +303,43 @@ private:
|
||||
bool m_will_erase;
|
||||
};
|
||||
|
||||
/** Abstract view on the open txout dataset. */
|
||||
/** Pure abstract view on the open txout dataset. */
|
||||
class CCoinsView
|
||||
{
|
||||
public:
|
||||
//! As we use CCoinsViews polymorphically, have a virtual destructor
|
||||
virtual ~CCoinsView() = default;
|
||||
|
||||
//! Retrieve the Coin (unspent transaction output) for a given outpoint.
|
||||
//! May populate the cache. Use PeekCoin() to perform a non-caching lookup.
|
||||
virtual std::optional<Coin> GetCoin(const COutPoint& outpoint) const;
|
||||
virtual std::optional<Coin> GetCoin(const COutPoint& outpoint) const = 0;
|
||||
|
||||
//! Retrieve the Coin (unspent transaction output) for a given outpoint, without caching results.
|
||||
//! Does not populate the cache. Use GetCoin() to cache the result.
|
||||
virtual std::optional<Coin> PeekCoin(const COutPoint& outpoint) const;
|
||||
virtual std::optional<Coin> PeekCoin(const COutPoint& outpoint) const = 0;
|
||||
|
||||
//! Just check whether a given outpoint is unspent.
|
||||
//! May populate the cache. Use PeekCoin() to perform a non-caching lookup.
|
||||
virtual bool HaveCoin(const COutPoint& outpoint) const;
|
||||
virtual bool HaveCoin(const COutPoint& outpoint) const = 0;
|
||||
|
||||
//! Retrieve the block hash whose state this CCoinsView currently represents
|
||||
virtual uint256 GetBestBlock() const;
|
||||
virtual uint256 GetBestBlock() const = 0;
|
||||
|
||||
//! Retrieve the range of blocks that may have been only partially written.
|
||||
//! If the database is in a consistent state, the result is the empty vector.
|
||||
//! Otherwise, a two-element vector is returned consisting of the new and
|
||||
//! the old block hash, in that order.
|
||||
virtual std::vector<uint256> GetHeadBlocks() const;
|
||||
virtual std::vector<uint256> GetHeadBlocks() const = 0;
|
||||
|
||||
//! Do a bulk modification (multiple Coin changes + BestBlock change).
|
||||
//! The passed cursor is used to iterate through the coins.
|
||||
virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash);
|
||||
virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& block_hash) = 0;
|
||||
|
||||
//! Get a cursor to iterate over the whole state
|
||||
virtual std::unique_ptr<CCoinsViewCursor> Cursor() const;
|
||||
//! Get a cursor to iterate over the whole state. Implementations may return nullptr.
|
||||
virtual std::unique_ptr<CCoinsViewCursor> Cursor() const = 0;
|
||||
|
||||
//! As we use CCoinsViews polymorphically, have a virtual destructor
|
||||
virtual ~CCoinsView() = default;
|
||||
|
||||
//! Estimate database size (0 if not implemented)
|
||||
virtual size_t EstimateSize() const { return 0; }
|
||||
//! Estimate database size
|
||||
virtual size_t EstimateSize() const = 0;
|
||||
};
|
||||
|
||||
/** Noop coins view. */
|
||||
@@ -353,6 +353,18 @@ public:
|
||||
|
||||
CoinsViewEmpty(const CoinsViewEmpty&) = delete;
|
||||
CoinsViewEmpty& operator=(const CoinsViewEmpty&) = delete;
|
||||
|
||||
std::optional<Coin> GetCoin(const COutPoint&) const override { return {}; }
|
||||
std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override { return GetCoin(outpoint); }
|
||||
bool HaveCoin(const COutPoint& outpoint) const override { return !!GetCoin(outpoint); }
|
||||
uint256 GetBestBlock() const override { return {}; }
|
||||
std::vector<uint256> GetHeadBlocks() const override { return {}; }
|
||||
void BatchWrite(CoinsViewCacheCursor& cursor, const uint256&) override
|
||||
{
|
||||
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { }
|
||||
}
|
||||
std::unique_ptr<CCoinsViewCursor> Cursor() const override { return {}; }
|
||||
size_t EstimateSize() const override { return 0; }
|
||||
};
|
||||
|
||||
/** CCoinsView backed by another CCoinsView */
|
||||
|
||||
@@ -247,7 +247,7 @@ FUZZ_TARGET(coinscache_sim)
|
||||
CallOneOf(
|
||||
provider,
|
||||
|
||||
[&]() { // GetCoin
|
||||
[&]() { // PeekCoin/GetCoin
|
||||
uint32_t outpointidx = provider.ConsumeIntegralInRange<uint32_t>(0, NUM_OUTPOINTS - 1);
|
||||
// Look up in simulation data.
|
||||
auto sim = lookup(outpointidx);
|
||||
|
||||
@@ -78,6 +78,11 @@ std::optional<Coin> CCoinsViewDB::GetCoin(const COutPoint& outpoint) const
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<Coin> CCoinsViewDB::PeekCoin(const COutPoint& outpoint) const
|
||||
{
|
||||
return GetCoin(outpoint);
|
||||
}
|
||||
|
||||
bool CCoinsViewDB::HaveCoin(const COutPoint& outpoint) const
|
||||
{
|
||||
return m_db->Exists(CoinEntry(&outpoint));
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
explicit CCoinsViewDB(DBParams db_params, CoinsViewOptions options);
|
||||
|
||||
std::optional<Coin> GetCoin(const COutPoint& outpoint) const override;
|
||||
std::optional<Coin> PeekCoin(const COutPoint& outpoint) const override;
|
||||
bool HaveCoin(const COutPoint& outpoint) const override;
|
||||
uint256 GetBestBlock() const override;
|
||||
std::vector<uint256> GetHeadBlocks() const override;
|
||||
|
||||
@@ -768,7 +768,7 @@ protected:
|
||||
public:
|
||||
CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn);
|
||||
/** GetCoin, returning whether it exists and is not spent. Also updates m_non_base_coins if the
|
||||
* coin is not fetched from base. */
|
||||
* coin is not fetched from base. May populate the base view on cache misses. */
|
||||
std::optional<Coin> GetCoin(const COutPoint& outpoint) const override;
|
||||
/** Add the coins created by this transaction. These coins are only temporarily stored in
|
||||
* m_temp_added and cannot be flushed to the back end. Only used for package validation. */
|
||||
|
||||
Reference in New Issue
Block a user