mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-08 10:31:50 -05:00
refactor: wrap CCoinsViewCursor in unique_ptr
Specifically with CCoinsViewDB, if a raw cursor is allocated and not freed, a cryptic leveldb assertion failure occurs on CCoinsViewDB destruction. See: https://github.com/google/leveldb/issues/142#issuecomment-414418135
This commit is contained in:
parent
6bc1eca01b
commit
615c1adfb0
6 changed files with 15 additions and 14 deletions
|
@ -13,7 +13,7 @@ bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return f
|
||||||
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
||||||
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
|
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<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 nullptr; }
|
std::unique_ptr<CCoinsViewCursor> CCoinsView::Cursor() const { return nullptr; }
|
||||||
|
|
||||||
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
|
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,7 @@ uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
||||||
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
|
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
|
||||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||||
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
|
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
|
||||||
CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
|
std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); }
|
||||||
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
|
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
|
||||||
|
|
||||||
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), cachedCoinsUsage(0) {}
|
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), cachedCoinsUsage(0) {}
|
||||||
|
|
|
@ -180,7 +180,7 @@ public:
|
||||||
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||||
|
|
||||||
//! Get a cursor to iterate over the whole state
|
//! Get a cursor to iterate over the whole state
|
||||||
virtual CCoinsViewCursor *Cursor() const;
|
virtual std::unique_ptr<CCoinsViewCursor> Cursor() const;
|
||||||
|
|
||||||
//! As we use CCoinsViews polymorphically, have a virtual destructor
|
//! As we use CCoinsViews polymorphically, have a virtual destructor
|
||||||
virtual ~CCoinsView() {}
|
virtual ~CCoinsView() {}
|
||||||
|
@ -204,7 +204,7 @@ public:
|
||||||
std::vector<uint256> GetHeadBlocks() const override;
|
std::vector<uint256> GetHeadBlocks() const override;
|
||||||
void SetBackend(CCoinsView &viewIn);
|
void SetBackend(CCoinsView &viewIn);
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
||||||
CCoinsViewCursor *Cursor() const override;
|
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
|
||||||
size_t EstimateSize() const override;
|
size_t EstimateSize() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ public:
|
||||||
uint256 GetBestBlock() const override;
|
uint256 GetBestBlock() const override;
|
||||||
void SetBestBlock(const uint256 &hashBlock);
|
void SetBestBlock(const uint256 &hashBlock);
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
||||||
CCoinsViewCursor* Cursor() const override {
|
std::unique_ptr<CCoinsViewCursor> Cursor() const override {
|
||||||
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2391,7 +2391,7 @@ static RPCHelpMan scantxoutset()
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
CChainState& active_chainstate = chainman.ActiveChainstate();
|
CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||||
active_chainstate.ForceFlushStateToDisk();
|
active_chainstate.ForceFlushStateToDisk();
|
||||||
pcursor = std::unique_ptr<CCoinsViewCursor>(active_chainstate.CoinsDB().Cursor());
|
pcursor = active_chainstate.CoinsDB().Cursor();
|
||||||
CHECK_NONFATAL(pcursor);
|
CHECK_NONFATAL(pcursor);
|
||||||
tip = active_chainstate.m_chain.Tip();
|
tip = active_chainstate.m_chain.Tip();
|
||||||
CHECK_NONFATAL(tip);
|
CHECK_NONFATAL(tip);
|
||||||
|
@ -2590,7 +2590,7 @@ UniValue CreateUTXOSnapshot(NodeContext& node, CChainState& chainstate, CAutoFil
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
|
||||||
}
|
}
|
||||||
|
|
||||||
pcursor = std::unique_ptr<CCoinsViewCursor>(chainstate.CoinsDB().Cursor());
|
pcursor = chainstate.CoinsDB().Cursor();
|
||||||
tip = chainstate.m_blockman.LookupBlockIndex(stats.hashBlock);
|
tip = chainstate.m_blockman.LookupBlockIndex(stats.hashBlock);
|
||||||
CHECK_NONFATAL(tip);
|
CHECK_NONFATAL(tip);
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,8 +183,8 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const CCoinsViewCursor* coins_view_cursor = backend_coins_view.Cursor();
|
std::unique_ptr<CCoinsViewCursor> coins_view_cursor = backend_coins_view.Cursor();
|
||||||
assert(coins_view_cursor == nullptr);
|
assert(!coins_view_cursor);
|
||||||
(void)backend_coins_view.EstimateSize();
|
(void)backend_coins_view.EstimateSize();
|
||||||
(void)backend_coins_view.GetBestBlock();
|
(void)backend_coins_view.GetBestBlock();
|
||||||
(void)backend_coins_view.GetHeadBlocks();
|
(void)backend_coins_view.GetHeadBlocks();
|
||||||
|
|
|
@ -168,9 +168,10 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
|
||||||
return Read(DB_LAST_BLOCK, nFile);
|
return Read(DB_LAST_BLOCK, nFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCoinsViewCursor *CCoinsViewDB::Cursor() const
|
std::unique_ptr<CCoinsViewCursor> CCoinsViewDB::Cursor() const
|
||||||
{
|
{
|
||||||
CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper&>(*m_db).NewIterator(), GetBestBlock());
|
auto i = std::make_unique<CCoinsViewDBCursor>(
|
||||||
|
const_cast<CDBWrapper&>(*m_db).NewIterator(), GetBestBlock());
|
||||||
/* It seems that there are no "const iterators" for LevelDB. Since we
|
/* It seems that there are no "const iterators" for LevelDB. Since we
|
||||||
only need read operations on it, use a const-cast to get around
|
only need read operations on it, use a const-cast to get around
|
||||||
that restriction. */
|
that restriction. */
|
||||||
|
|
|
@ -60,7 +60,7 @@ public:
|
||||||
uint256 GetBestBlock() const override;
|
uint256 GetBestBlock() const override;
|
||||||
std::vector<uint256> GetHeadBlocks() const override;
|
std::vector<uint256> GetHeadBlocks() const override;
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
||||||
CCoinsViewCursor *Cursor() const override;
|
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
|
||||||
|
|
||||||
//! Attempt to update from an older database format. Returns whether an error occurred.
|
//! Attempt to update from an older database format. Returns whether an error occurred.
|
||||||
bool Upgrade();
|
bool Upgrade();
|
||||||
|
@ -74,6 +74,8 @@ public:
|
||||||
class CCoinsViewDBCursor: public CCoinsViewCursor
|
class CCoinsViewDBCursor: public CCoinsViewCursor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256 &hashBlockIn):
|
||||||
|
CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
|
||||||
~CCoinsViewDBCursor() {}
|
~CCoinsViewDBCursor() {}
|
||||||
|
|
||||||
bool GetKey(COutPoint &key) const override;
|
bool GetKey(COutPoint &key) const override;
|
||||||
|
@ -84,8 +86,6 @@ public:
|
||||||
void Next() override;
|
void Next() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256 &hashBlockIn):
|
|
||||||
CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
|
|
||||||
std::unique_ptr<CDBIterator> pcursor;
|
std::unique_ptr<CDBIterator> pcursor;
|
||||||
std::pair<char, COutPoint> keyTmp;
|
std::pair<char, COutPoint> keyTmp;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue