Skip to content

Commit d7c97ed

Browse files
committed
move-only: make the CChainState interface public
along with DisconnectResult, and CBlockIndexWorkComparator. The CChainState interface needs to be known to the rest of the system because many global functions will move to CChainState methods. This is to allow other parts of the system to be parameterized per chainstate instance instead of assuming a single global.
1 parent c459c5f commit d7c97ed

File tree

2 files changed

+155
-155
lines changed

2 files changed

+155
-155
lines changed

src/validation.cpp

Lines changed: 15 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -60,165 +60,25 @@
6060
#define MICRO 0.000001
6161
#define MILLI 0.001
6262

63-
/**
64-
* Global state
65-
*/
66-
namespace {
67-
struct CBlockIndexWorkComparator
68-
{
69-
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const {
70-
// First sort by most total work, ...
71-
if (pa->nChainWork > pb->nChainWork) return false;
72-
if (pa->nChainWork < pb->nChainWork) return true;
73-
74-
// ... then by earliest time received, ...
75-
if (pa->nSequenceId < pb->nSequenceId) return false;
76-
if (pa->nSequenceId > pb->nSequenceId) return true;
77-
78-
// Use pointer address as tie breaker (should only happen with blocks
79-
// loaded from disk, as those all have id 0).
80-
if (pa < pb) return false;
81-
if (pa > pb) return true;
82-
83-
// Identical blocks.
84-
return false;
85-
}
86-
};
87-
} // anon namespace
88-
89-
enum DisconnectResult
90-
{
91-
DISCONNECT_OK, // All good.
92-
DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
93-
DISCONNECT_FAILED // Something else went wrong.
94-
};
95-
96-
class ConnectTrace;
97-
98-
/**
99-
* CChainState stores and provides an API to update our local knowledge of the
100-
* current best chain and header tree.
101-
*
102-
* It generally provides access to the current block tree, as well as functions
103-
* to provide new data, which it will appropriately validate and incorporate in
104-
* its state as necessary.
105-
*
106-
* Eventually, the API here is targeted at being exposed externally as a
107-
* consumable libconsensus library, so any functions added must only call
108-
* other class member functions, pure functions in other parts of the consensus
109-
* library, callbacks via the validation interface, or read/write-to-disk
110-
* functions (eventually this will also be via callbacks).
111-
*/
112-
class CChainState {
113-
private:
114-
/**
115-
* The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
116-
* as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
117-
* missing the data for the block.
118-
*/
119-
std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
120-
121-
/**
122-
* Every received block is assigned a unique and increasing identifier, so we
123-
* know which one to give priority in case of a fork.
124-
*/
125-
CCriticalSection cs_nBlockSequenceId;
126-
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
127-
int32_t nBlockSequenceId = 1;
128-
/** Decreasing counter (used by subsequent preciousblock calls). */
129-
int32_t nBlockReverseSequenceId = -1;
130-
/** chainwork for the last block that preciousblock has been applied to. */
131-
arith_uint256 nLastPreciousChainwork = 0;
132-
133-
/** In order to efficiently track invalidity of headers, we keep the set of
134-
* blocks which we tried to connect and found to be invalid here (ie which
135-
* were set to BLOCK_FAILED_VALID since the last restart). We can then
136-
* walk this set and check if a new header is a descendant of something in
137-
* this set, preventing us from having to walk mapBlockIndex when we try
138-
* to connect a bad block and fail.
139-
*
140-
* While this is more complicated than marking everything which descends
141-
* from an invalid block as invalid at the time we discover it to be
142-
* invalid, doing so would require walking all of mapBlockIndex to find all
143-
* descendants. Since this case should be very rare, keeping track of all
144-
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
145-
* well.
146-
*
147-
* Because we already walk mapBlockIndex in height-order at startup, we go
148-
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
149-
* instead of putting things in this set.
150-
*/
151-
std::set<CBlockIndex*> m_failed_blocks;
152-
153-
/**
154-
* the ChainState CriticalSection
155-
* A lock that must be held when modifying this ChainState - held in ActivateBestChain()
156-
*/
157-
CCriticalSection m_cs_chainstate;
158-
159-
public:
160-
//! The current chain of blockheaders we consult and build on.
161-
//! @see CChain, CBlockIndex.
162-
CChain m_chain;
163-
BlockMap mapBlockIndex GUARDED_BY(cs_main);
164-
std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
165-
CBlockIndex *pindexBestInvalid = nullptr;
166-
167-
bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
168-
169-
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) LOCKS_EXCLUDED(cs_main);
170-
171-
/**
172-
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
173-
* that it doesn't descend from an invalid block, and then add it to mapBlockIndex.
174-
*/
175-
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
176-
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
63+
bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIndex *pb) const {
64+
// First sort by most total work, ...
65+
if (pa->nChainWork > pb->nChainWork) return false;
66+
if (pa->nChainWork < pb->nChainWork) return true;
17767

178-
// Block (dis)connection on a given view:
179-
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
180-
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
181-
CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
68+
// ... then by earliest time received, ...
69+
if (pa->nSequenceId < pb->nSequenceId) return false;
70+
if (pa->nSequenceId > pb->nSequenceId) return true;
18271

183-
// Block disconnection on our pcoinsTip:
184-
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
72+
// Use pointer address as tie breaker (should only happen with blocks
73+
// loaded from disk, as those all have id 0).
74+
if (pa < pb) return false;
75+
if (pa > pb) return true;
18576

186-
// Manual block validity manipulation:
187-
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
188-
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
189-
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
190-
191-
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
192-
bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
193-
bool LoadGenesisBlock(const CChainParams& chainparams);
194-
195-
void PruneBlockIndexCandidates();
196-
197-
void UnloadBlockIndex();
198-
199-
private:
200-
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
201-
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
202-
203-
CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
204-
/** Create a new block index entry for a given block hash */
205-
CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
206-
/**
207-
* Make various assertions about the state of the block index.
208-
*
209-
* By default this only executes fully when using the Regtest chain; see: fCheckBlockIndex.
210-
*/
211-
void CheckBlockIndex(const Consensus::Params& consensusParams);
212-
213-
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
214-
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
215-
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
216-
217-
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
77+
// Identical blocks.
78+
return false;
79+
}
21880

219-
//! Mark a block as not having block data
220-
void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
221-
} g_chainstate;
81+
CChainState g_chainstate;
22282

22383
CChain& ChainActive() { return g_chainstate.m_chain; }
22484

src/validation.h

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class CTxMemPool;
4444
class CValidationState;
4545
struct ChainTxData;
4646

47+
struct DisconnectedBlockTransactions;
4748
struct PrecomputedTransactionData;
4849
struct LockPoints;
4950

@@ -422,6 +423,145 @@ inline CBlockIndex* LookupBlockIndex(const uint256& hash)
422423
/** Find the last common block between the parameter chain and a locator. */
423424
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
424425

426+
enum DisconnectResult
427+
{
428+
DISCONNECT_OK, // All good.
429+
DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
430+
DISCONNECT_FAILED // Something else went wrong.
431+
};
432+
433+
class ConnectTrace;
434+
435+
struct CBlockIndexWorkComparator
436+
{
437+
bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const;
438+
};
439+
440+
/**
441+
* CChainState stores and provides an API to update our local knowledge of the
442+
* current best chain and header tree.
443+
*
444+
* It generally provides access to the current block tree, as well as functions
445+
* to provide new data, which it will appropriately validate and incorporate in
446+
* its state as necessary.
447+
*
448+
* Eventually, the API here is targeted at being exposed externally as a
449+
* consumable libconsensus library, so any functions added must only call
450+
* other class member functions, pure functions in other parts of the consensus
451+
* library, callbacks via the validation interface, or read/write-to-disk
452+
* functions (eventually this will also be via callbacks).
453+
*/
454+
class CChainState {
455+
private:
456+
/**
457+
* The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
458+
* as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
459+
* missing the data for the block.
460+
*/
461+
std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
462+
463+
/**
464+
* Every received block is assigned a unique and increasing identifier, so we
465+
* know which one to give priority in case of a fork.
466+
*/
467+
CCriticalSection cs_nBlockSequenceId;
468+
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
469+
int32_t nBlockSequenceId = 1;
470+
/** Decreasing counter (used by subsequent preciousblock calls). */
471+
int32_t nBlockReverseSequenceId = -1;
472+
/** chainwork for the last block that preciousblock has been applied to. */
473+
arith_uint256 nLastPreciousChainwork = 0;
474+
475+
/** In order to efficiently track invalidity of headers, we keep the set of
476+
* blocks which we tried to connect and found to be invalid here (ie which
477+
* were set to BLOCK_FAILED_VALID since the last restart). We can then
478+
* walk this set and check if a new header is a descendant of something in
479+
* this set, preventing us from having to walk mapBlockIndex when we try
480+
* to connect a bad block and fail.
481+
*
482+
* While this is more complicated than marking everything which descends
483+
* from an invalid block as invalid at the time we discover it to be
484+
* invalid, doing so would require walking all of mapBlockIndex to find all
485+
* descendants. Since this case should be very rare, keeping track of all
486+
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
487+
* well.
488+
*
489+
* Because we already walk mapBlockIndex in height-order at startup, we go
490+
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
491+
* instead of putting things in this set.
492+
*/
493+
std::set<CBlockIndex*> m_failed_blocks;
494+
495+
/**
496+
* the ChainState CriticalSection
497+
* A lock that must be held when modifying this ChainState - held in ActivateBestChain()
498+
*/
499+
CCriticalSection m_cs_chainstate;
500+
501+
public:
502+
//! The current chain of blockheaders we consult and build on.
503+
//! @see CChain, CBlockIndex.
504+
CChain m_chain;
505+
BlockMap mapBlockIndex GUARDED_BY(cs_main);
506+
std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
507+
CBlockIndex *pindexBestInvalid = nullptr;
508+
509+
bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
510+
511+
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) LOCKS_EXCLUDED(cs_main);
512+
513+
/**
514+
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
515+
* that it doesn't descend from an invalid block, and then add it to mapBlockIndex.
516+
*/
517+
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
518+
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
519+
520+
// Block (dis)connection on a given view:
521+
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
522+
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
523+
CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
524+
525+
// Block disconnection on our pcoinsTip:
526+
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
527+
528+
// Manual block validity manipulation:
529+
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
530+
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
531+
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
532+
533+
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
534+
bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main);
535+
bool LoadGenesisBlock(const CChainParams& chainparams);
536+
537+
void PruneBlockIndexCandidates();
538+
539+
void UnloadBlockIndex();
540+
541+
private:
542+
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
543+
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
544+
545+
CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
546+
/** Create a new block index entry for a given block hash */
547+
CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
548+
/**
549+
* Make various assertions about the state of the block index.
550+
*
551+
* By default this only executes fully when using the Regtest chain; see: fCheckBlockIndex.
552+
*/
553+
void CheckBlockIndex(const Consensus::Params& consensusParams);
554+
555+
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
556+
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
557+
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
558+
559+
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
560+
561+
//! Mark a block as not having block data
562+
void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
563+
};
564+
425565
/** Mark a block as precious and reorganize.
426566
*
427567
* May not be called in a

0 commit comments

Comments
 (0)