Skip to content

Commit 52c8ef2

Browse files
MarcoFalkePastaPastaPasta
authored andcommitted
Merge bitcoin#22263: refactor: wrap CCoinsViewCursor in unique_ptr
7ad414f doc: add comment about CCoinsViewDBCursor constructor (James O'Beirne) 0f8a5a4 move-only(ish): don't expose CCoinsViewDBCursor (James O'Beirne) 615c1ad refactor: wrap CCoinsViewCursor in unique_ptr (James O'Beirne) Pull request description: I tripped over this one for a few hours at the beginning of the week, so I've sort of got a personal vendetta against `CCoinsView::Cursor()` returning a raw pointer. Specifically in the case of CCoinsViewDB, if a raw cursor is allocated and not freed, a cryptic leveldb assertion failure occurs on CCoinsViewDB destruction (`Assertion 'dummy_versions_.next_ == &dummy_versions_' failed.`). This is a pretty simple change. Related to: bitcoin#21766 See also: google/leveldb#142 (comment) ACKs for top commit: MarcoFalke: review ACK 7ad414f 🔎 jonatack: re-ACK 7ad414f modulo suggestion ryanofsky: Code review ACK 7ad414f. Two new commits look good and thanks for clarifying constructor comment Tree-SHA512: 6471d03e2de674d84b1ea0d31e25f433d52aa1aa4996f7b4aab1bd02b6bc340b15e64cc8ea07bbefefa3b5da35384ca5400cc230434e787c30931b8574c672f9
1 parent 56af7d6 commit 52c8ef2

File tree

6 files changed

+37
-34
lines changed

6 files changed

+37
-34
lines changed

src/coins.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return f
1313
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
1414
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
1515
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
16-
CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; }
16+
std::unique_ptr<CCoinsViewCursor> CCoinsView::Cursor() const { return nullptr; }
1717

1818
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
1919
{
@@ -28,7 +28,7 @@ uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
2828
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
2929
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
3030
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
31-
CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
31+
std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); }
3232
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
3333

3434
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), cachedCoinsUsage(0) {}

src/coins.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ class CCoinsView
180180
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
181181

182182
//! Get a cursor to iterate over the whole state
183-
virtual CCoinsViewCursor *Cursor() const;
183+
virtual std::unique_ptr<CCoinsViewCursor> Cursor() const;
184184

185185
//! As we use CCoinsViews polymorphically, have a virtual destructor
186186
virtual ~CCoinsView() {}
@@ -204,7 +204,7 @@ class CCoinsViewBacked : public CCoinsView
204204
std::vector<uint256> GetHeadBlocks() const override;
205205
void SetBackend(CCoinsView &viewIn);
206206
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
207-
CCoinsViewCursor *Cursor() const override;
207+
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
208208
size_t EstimateSize() const override;
209209
};
210210

@@ -237,7 +237,7 @@ class CCoinsViewCache : public CCoinsViewBacked
237237
uint256 GetBestBlock() const override;
238238
void SetBestBlock(const uint256 &hashBlock);
239239
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
240-
CCoinsViewCursor* Cursor() const override {
240+
std::unique_ptr<CCoinsViewCursor> Cursor() const override {
241241
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
242242
}
243243

src/rpc/blockchain.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,7 +2734,7 @@ UniValue scantxoutset(const JSONRPCRequest& request)
27342734
LOCK(cs_main);
27352735
CChainState& active_chainstate = chainman.ActiveChainstate();
27362736
active_chainstate.ForceFlushStateToDisk();
2737-
pcursor = std::unique_ptr<CCoinsViewCursor>(active_chainstate.CoinsDB().Cursor());
2737+
pcursor = active_chainstate.CoinsDB().Cursor();
27382738
CHECK_NONFATAL(pcursor);
27392739
tip = active_chainstate.m_chain.Tip();
27402740
CHECK_NONFATAL(tip);
@@ -2923,7 +2923,7 @@ UniValue CreateUTXOSnapshot(NodeContext& node, CChainState& chainstate, CAutoFil
29232923
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
29242924
}
29252925

2926-
pcursor = std::unique_ptr<CCoinsViewCursor>(chainstate.CoinsDB().Cursor());
2926+
pcursor = chainstate.CoinsDB().Cursor();
29272927
tip = chainstate.m_blockman.LookupBlockIndex(stats.hashBlock);
29282928
CHECK_NONFATAL(tip);
29292929
}

src/test/fuzz/coins_view.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
180180
}
181181

182182
{
183-
const CCoinsViewCursor* coins_view_cursor = backend_coins_view.Cursor();
184-
assert(coins_view_cursor == nullptr);
183+
std::unique_ptr<CCoinsViewCursor> coins_view_cursor = backend_coins_view.Cursor();
184+
assert(!coins_view_cursor);
185185
(void)backend_coins_view.EstimateSize();
186186
(void)backend_coins_view.GetBestBlock();
187187
(void)backend_coins_view.GetHeadBlocks();

src/txdb.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,34 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
172172
return Read(DB_LAST_BLOCK, nFile);
173173
}
174174

175-
CCoinsViewCursor *CCoinsViewDB::Cursor() const
175+
/** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
176+
class CCoinsViewDBCursor: public CCoinsViewCursor
176177
{
177-
CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper&>(*m_db).NewIterator(), GetBestBlock());
178+
public:
179+
// Prefer using CCoinsViewDB::Cursor() since we want to perform some
180+
// cache warmup on instantiation.
181+
CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256&hashBlockIn):
182+
CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
183+
~CCoinsViewDBCursor() {}
184+
185+
bool GetKey(COutPoint &key) const override;
186+
bool GetValue(Coin &coin) const override;
187+
unsigned int GetValueSize() const override;
188+
189+
bool Valid() const override;
190+
void Next() override;
191+
192+
private:
193+
std::unique_ptr<CDBIterator> pcursor;
194+
std::pair<char, COutPoint> keyTmp;
195+
196+
friend class CCoinsViewDB;
197+
};
198+
199+
std::unique_ptr<CCoinsViewCursor> CCoinsViewDB::Cursor() const
200+
{
201+
auto i = std::make_unique<CCoinsViewDBCursor>(
202+
const_cast<CDBWrapper&>(*m_db).NewIterator(), GetBestBlock());
178203
/* It seems that there are no "const iterators" for LevelDB. Since we
179204
only need read operations on it, use a const-cast to get around
180205
that restriction. */

src/txdb.h

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CCoinsViewDB final : public CCoinsView
6363
uint256 GetBestBlock() const override;
6464
std::vector<uint256> GetHeadBlocks() const override;
6565
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
66-
CCoinsViewCursor *Cursor() const override;
66+
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
6767

6868
//! Attempt to update from an older database format. Returns whether an error occurred.
6969
bool Upgrade();
@@ -73,28 +73,6 @@ class CCoinsViewDB final : public CCoinsView
7373
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
7474
};
7575

76-
/** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
77-
class CCoinsViewDBCursor: public CCoinsViewCursor
78-
{
79-
public:
80-
~CCoinsViewDBCursor() {}
81-
82-
bool GetKey(COutPoint &key) const override;
83-
bool GetValue(Coin &coin) const override;
84-
unsigned int GetValueSize() const override;
85-
86-
bool Valid() const override;
87-
void Next() override;
88-
89-
private:
90-
CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256 &hashBlockIn):
91-
CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
92-
std::unique_ptr<CDBIterator> pcursor;
93-
std::pair<char, COutPoint> keyTmp;
94-
95-
friend class CCoinsViewDB;
96-
};
97-
9876
/** Access to the block database (blocks/index/) */
9977
class CBlockTreeDB : public CDBWrapper
10078
{

0 commit comments

Comments
 (0)