validation: remove sentinel block from ConnectTrace
What changed, and why it matters
This is a small internal cleanup in Bitcoin Core's block-processing code. It removes an obsolete placeholder ('sentinel') entry that was kept in a list of connected blocks to support an old feature that no longer exists. The change simplifies the code but does not fix a security bug or change network behavior.
No security action needed; treat as normal code cleanup and review for correctness during ordinary merge review.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors ConnectTrace in src/validation.cpp. Previously the class pre-allocated one empty PerBlockConnectTrace sentinel at the end of blocksConnected so that conflicted-transaction tracking could be filled in before the block was recorded; that tracking was removed in an earlier commit (5613f9842b4000fed088b8cf7b99674c328d15e1). The patch deletes the sentinel, makes BlockConnected append a fully populated entry directly, and makes GetBlocksConnected() return a const reference without popping anything. It is a code-quality refactor with no functional security impact evident from the diff.
Changed components
src/validation.cppConnectTracePerBlockConnectTraceInspect captured patch +5 / −20
diff --git a/src/validation.cpp b/src/validation.cpp
index 67130a31..b462b7f0 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2990,39 +2990,24 @@ bool Chainstate::DisconnectTip(BlockValidationState& state, DisconnectedBlockTra
struct PerBlockConnectTrace {
CBlockIndex* pindex = nullptr;
std::shared_ptr<const CBlock> pblock;
- PerBlockConnectTrace() = default;
};
/**
* Used to track blocks whose transactions were applied to the UTXO state as a
* part of a single ActivateBestChainStep call.
- *
- * This class is single-use, once you call GetBlocksConnected() you have to throw
- * it away and make a new one.
*/
class ConnectTrace {
private:
std::vector<PerBlockConnectTrace> blocksConnected;
public:
- explicit ConnectTrace() : blocksConnected(1) {}
-
void BlockConnected(CBlockIndex* pindex, std::shared_ptr<const CBlock> pblock) {
- assert(!blocksConnected.back().pindex);
assert(pindex);
assert(pblock);
- blocksConnected.back().pindex = pindex;
- blocksConnected.back().pblock = std::move(pblock);
- blocksConnected.emplace_back();
- }
-
- std::vector<PerBlockConnectTrace>& GetBlocksConnected() {
- // We always keep one extra block at the end of our list because
- // blocks are added after all the conflicted transactions have
- // been filled in. Thus, the last entry should always be an empty
- // one waiting for the transactions from the next block. We pop
- // the last entry here to make sure the list we return is sane.
- assert(!blocksConnected.back().pindex);
- blocksConnected.pop_back();
+ blocksConnected.emplace_back(pindex, std::move(pblock));
+ }
+
+ const std::vector<PerBlockConnectTrace>& GetBlocksConnected() const
+ {
return blocksConnected;
}
};
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.