@ -60,165 +60,25 @@
# define MICRO 0.000001
# define MILLI 0.001
/**
* Global state
*/
namespace {
struct CBlockIndexWorkComparator
{
bool operator ( ) ( const CBlockIndex * pa , const CBlockIndex * pb ) const {
// First sort by most total work, ...
if ( pa - > nChainWork > pb - > nChainWork ) return false ;
if ( pa - > nChainWork < pb - > nChainWork ) return true ;
// ... then by earliest time received, ...
if ( pa - > nSequenceId < pb - > nSequenceId ) return false ;
if ( pa - > nSequenceId > pb - > nSequenceId ) return true ;
// Use pointer address as tie breaker (should only happen with blocks
// loaded from disk, as those all have id 0).
if ( pa < pb ) return false ;
if ( pa > pb ) return true ;
// Identical blocks.
return false ;
}
} ;
} // anon namespace
enum DisconnectResult
{
DISCONNECT_OK , // All good.
DISCONNECT_UNCLEAN , // Rolled back, but UTXO set was inconsistent with block.
DISCONNECT_FAILED // Something else went wrong.
} ;
class ConnectTrace ;
/**
* CChainState stores and provides an API to update our local knowledge of the
* current best chain and header tree .
*
* It generally provides access to the current block tree , as well as functions
* to provide new data , which it will appropriately validate and incorporate in
* its state as necessary .
*
* Eventually , the API here is targeted at being exposed externally as a
* consumable libconsensus library , so any functions added must only call
* other class member functions , pure functions in other parts of the consensus
* library , callbacks via the validation interface , or read / write - to - disk
* functions ( eventually this will also be via callbacks ) .
*/
class CChainState {
private :
/**
* The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS ( for itself and all ancestors ) and
* as good as our current tip or better . Entries may be failed , though , and pruning nodes may be
* missing the data for the block .
*/
std : : set < CBlockIndex * , CBlockIndexWorkComparator > setBlockIndexCandidates ;
/**
* Every received block is assigned a unique and increasing identifier , so we
* know which one to give priority in case of a fork .
*/
CCriticalSection cs_nBlockSequenceId ;
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
int32_t nBlockSequenceId = 1 ;
/** Decreasing counter (used by subsequent preciousblock calls). */
int32_t nBlockReverseSequenceId = - 1 ;
/** chainwork for the last block that preciousblock has been applied to. */
arith_uint256 nLastPreciousChainwork = 0 ;
/** In order to efficiently track invalidity of headers, we keep the set of
* blocks which we tried to connect and found to be invalid here ( ie which
* were set to BLOCK_FAILED_VALID since the last restart ) . We can then
* walk this set and check if a new header is a descendant of something in
* this set , preventing us from having to walk mapBlockIndex when we try
* to connect a bad block and fail .
*
* While this is more complicated than marking everything which descends
* from an invalid block as invalid at the time we discover it to be
* invalid , doing so would require walking all of mapBlockIndex to find all
* descendants . Since this case should be very rare , keeping track of all
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
* well .
*
* Because we already walk mapBlockIndex in height - order at startup , we go
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time ,
* instead of putting things in this set .
*/
std : : set < CBlockIndex * > m_failed_blocks ;
/**
* the ChainState CriticalSection
* A lock that must be held when modifying this ChainState - held in ActivateBestChain ( )
*/
CCriticalSection m_cs_chainstate ;
public :
//! The current chain of blockheaders we consult and build on.
//! @see CChain, CBlockIndex.
CChain m_chain ;
BlockMap mapBlockIndex GUARDED_BY ( cs_main ) ;
std : : multimap < CBlockIndex * , CBlockIndex * > mapBlocksUnlinked ;
CBlockIndex * pindexBestInvalid = nullptr ;
bool LoadBlockIndex ( const Consensus : : Params & consensus_params , CBlockTreeDB & blocktree ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
bool ActivateBestChain ( CValidationState & state , const CChainParams & chainparams , std : : shared_ptr < const CBlock > pblock ) LOCKS_EXCLUDED ( cs_main ) ;
/**
* If a block header hasn ' t already been seen , call CheckBlockHeader on it , ensure
* that it doesn ' t descend from an invalid block , and then add it to mapBlockIndex .
*/
bool AcceptBlockHeader ( const CBlockHeader & block , CValidationState & state , const CChainParams & chainparams , CBlockIndex * * ppindex ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
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 ) ;
bool CBlockIndexWorkComparator : : operator ( ) ( const CBlockIndex * pa , const CBlockIndex * pb ) const {
// First sort by most total work, ...
if ( pa - > nChainWork > pb - > nChainWork ) return false ;
if ( pa - > nChainWork < pb - > nChainWork ) return true ;
// Block (dis)connection on a given view:
DisconnectResult DisconnectBlock ( const CBlock & block , const CBlockIndex * pindex , CCoinsViewCache & view ) ;
bool ConnectBlock ( const CBlock & block , CValidationState & state , CBlockIndex * pindex ,
CCoinsViewCache & view , const CChainParams & chainparams , bool fJustCheck = false ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
// ... then by earliest time received, ...
if ( pa - > nSequenceId < pb - > nSequenceId ) return false ;
if ( pa - > nSequenceId > pb - > nSequenceId ) return true ;
// Block disconnection on our pcoinsTip:
bool DisconnectTip ( CValidationState & state , const CChainParams & chainparams , DisconnectedBlockTransactions * disconnectpool ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
// Use pointer address as tie breaker (should only happen with blocks
// loaded from disk, as those all have id 0).
if ( pa < pb ) return false ;
if ( pa > pb ) return true ;
// Manual block validity manipulation:
bool PreciousBlock ( CValidationState & state , const CChainParams & params , CBlockIndex * pindex ) LOCKS_EXCLUDED ( cs_main ) ;
bool InvalidateBlock ( CValidationState & state , const CChainParams & chainparams , CBlockIndex * pindex ) LOCKS_EXCLUDED ( cs_main ) ;
void ResetBlockFailureFlags ( CBlockIndex * pindex ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
bool ReplayBlocks ( const CChainParams & params , CCoinsView * view ) ;
bool RewindBlockIndex ( const CChainParams & params ) LOCKS_EXCLUDED ( cs_main ) ;
bool LoadGenesisBlock ( const CChainParams & chainparams ) ;
void PruneBlockIndexCandidates ( ) ;
void UnloadBlockIndex ( ) ;
private :
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 ) ;
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 ) ;
CBlockIndex * AddToBlockIndex ( const CBlockHeader & block ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
/** Create a new block index entry for a given block hash */
CBlockIndex * InsertBlockIndex ( const uint256 & hash ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
/**
* Make various assertions about the state of the block index .
*
* By default this only executes fully when using the Regtest chain ; see : fCheckBlockIndex .
*/
void CheckBlockIndex ( const Consensus : : Params & consensusParams ) ;
void InvalidBlockFound ( CBlockIndex * pindex , const CValidationState & state ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
CBlockIndex * FindMostWorkChain ( ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
void ReceivedBlockTransactions ( const CBlock & block , CBlockIndex * pindexNew , const FlatFilePos & pos , const Consensus : : Params & consensusParams ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
bool RollforwardBlock ( const CBlockIndex * pindex , CCoinsViewCache & inputs , const CChainParams & params ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
// Identical blocks.
return false ;
}
//! Mark a block as not having block data
void EraseBlockData ( CBlockIndex * index ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main ) ;
} g_chainstate ;
CChainState g_chainstate ;
CChain & ChainActive ( ) { return g_chainstate . m_chain ; }