pub struct ChainState<PersistedState: ChainStore> {
inner: RwLock<ChainStateInner<PersistedState>>,
}Expand description
The high-level chain backend managing the blockchain state.
ChainState is responsible for:
- Keeping track of the chain state with the help of a
ChainStorefor persisted storage. - Correctly updating the state using consensus functions.
- Interfacing with other components and providing data about the current view of the chain.
Fields§
§inner: RwLock<ChainStateInner<PersistedState>>Implementations§
Source§impl<PersistedState: ChainStore> ChainState<PersistedState>
impl<PersistedState: ChainStore> ChainState<PersistedState>
fn maybe_reindex( &self, potential_tip: &DiskBlockHeader, ) -> Result<(), BlockchainError>
Sourcepub fn push_headers(
&self,
headers: Vec<BlockHeader>,
height: u32,
) -> Result<(), BlockchainError>
pub fn push_headers( &self, headers: Vec<BlockHeader>, height: u32, ) -> Result<(), BlockchainError>
Just adds headers to the chainstate, without validating them.
fn update_header(&self, header: &DiskBlockHeader) -> Result<(), BlockchainError>
fn update_header_and_index( &self, header: &DiskBlockHeader, hash: BlockHash, height: u32, ) -> Result<(), BlockchainError>
fn validate_header( &self, block_header: &BlockHeader, ) -> Result<BlockHash, BlockchainError>
Sourcefn is_genesis(&self, header: &BlockHeader) -> bool
fn is_genesis(&self, header: &BlockHeader) -> bool
Whether a node is the genesis block for this net
Sourcefn get_ancestor(
&self,
header: &BlockHeader,
) -> Result<DiskBlockHeader, BlockchainError>
fn get_ancestor( &self, header: &BlockHeader, ) -> Result<DiskBlockHeader, BlockchainError>
Returns the ancestor of a given block
Sourcefn get_branch_work(&self, header: &BlockHeader) -> Result<Work, BlockchainError>
fn get_branch_work(&self, header: &BlockHeader) -> Result<Work, BlockchainError>
Returns the cumulative work in this branch
Sourcefn check_branch(&self, branch_tip: &BlockHeader) -> Result<(), BlockchainError>
fn check_branch(&self, branch_tip: &BlockHeader) -> Result<(), BlockchainError>
Checks if a branch is valid (i.e. all ancestors are known)
Sourcefn get_chain_depth(
&self,
branch_tip: &BlockHeader,
) -> Result<u32, BlockchainError>
fn get_chain_depth( &self, branch_tip: &BlockHeader, ) -> Result<u32, BlockchainError>
Returns the depth of a branch (i.e. how many blocks are in the branch)
Sourcefn mark_chain_as_active(
&self,
new_tip: &BlockHeader,
fork_point: BlockHash,
) -> Result<(), BlockchainError>
fn mark_chain_as_active( &self, new_tip: &BlockHeader, fork_point: BlockHash, ) -> Result<(), BlockchainError>
Mark the current index as active, because we are in the middle of a reorg
Sourcefn mark_chain_as_inactive(
&self,
old_tip: &BlockHeader,
fork_point: BlockHash,
) -> Result<(), BlockchainError>
fn mark_chain_as_inactive( &self, old_tip: &BlockHeader, fork_point: BlockHash, ) -> Result<(), BlockchainError>
Mark the current index as inactive, either because we found an invalid ancestor, or we are in the middle of reorg
Sourcefn find_fork_point(
&self,
header: &BlockHeader,
) -> Result<BlockHeader, BlockchainError>
fn find_fork_point( &self, header: &BlockHeader, ) -> Result<BlockHeader, BlockchainError>
Finds where in the current index, a given branch forks out.
Sourcefn reorg_acc(&self, fork_point: &BlockHeader) -> Result<(), BlockchainError>
fn reorg_acc(&self, fork_point: &BlockHeader) -> Result<(), BlockchainError>
Changes the acc we are using to validate blocks.
fn reorg(&self, new_tip: BlockHeader) -> Result<(), BlockchainError>
Sourcefn change_active_chain(
&self,
new_tip: &BlockHeader,
last_valid: BlockHash,
depth: u32,
)
fn change_active_chain( &self, new_tip: &BlockHeader, last_valid: BlockHash, depth: u32, )
Changes the active chain to the new branch during a reorg
Sourcefn get_last_valid_block(
&self,
header: &BlockHeader,
) -> Result<BlockHash, BlockchainError>
fn get_last_valid_block( &self, header: &BlockHeader, ) -> Result<BlockHash, BlockchainError>
Grabs the last block we validated in this branch. We don’t validate a fork, unless it becomes the best chain. This function technically finds out what is the last common block between two branches.
Sourcefn maybe_reorg(&self, branch_tip: BlockHeader) -> Result<(), BlockchainError>
fn maybe_reorg(&self, branch_tip: BlockHeader) -> Result<(), BlockchainError>
If we get a header that doesn’t build on top of our best chain, it may cause a reorganization. We check this here.
Sourcefn push_alt_tip(&self, branch_tip: &BlockHeader) -> Result<(), BlockchainError>
fn push_alt_tip(&self, branch_tip: &BlockHeader) -> Result<(), BlockchainError>
Stores a new tip for a branch that is not the best one
Sourcefn chain_params(&self) -> ChainParams
fn chain_params(&self) -> ChainParams
Returns the chain_params struct for the current network
fn get_header_by_height( &self, height: u32, ) -> Result<DiskBlockHeader, BlockchainError>
fn notify( &self, block: &Block, height: u32, inputs: Option<&HashMap<OutPoint, UtxoData>>, )
fn new( chainstore: PersistedState, network: Network, assume_valid: AssumeValidArg, ) -> ChainState<PersistedState>
Sourcefn get_disk_block_header(
&self,
hash: &BlockHash,
) -> Result<DiskBlockHeader, BlockchainError>
fn get_disk_block_header( &self, hash: &BlockHash, ) -> Result<DiskBlockHeader, BlockchainError>
Fetches a DiskBlockHeader from the chain store given its block hash. Returns an error if
it’s not present or if the database operation failed.
Sourcefn get_roots_for_block(
&self,
height: u32,
) -> Result<Option<Stump>, BlockchainError>
fn get_roots_for_block( &self, height: u32, ) -> Result<Option<Stump>, BlockchainError>
Returns the parsed accumulator for a given block height, if they are present.
Sourcefn reindex_chain(&self) -> Result<(), BlockchainError>
fn reindex_chain(&self) -> Result<(), BlockchainError>
Re-indexes the chain if we find ourselves in an undefined state
Here, we have to find what’s the best chain we have, then figure out how many blocks we have validated. We then need to take extra care to align our accumulator with the validation index. If the validation_index diverges from the inner acc by even one block, all proofs will be invalid.
We start at the alleged validation index, and then we look for the last accumulator we have. If we don’t have the accumulator for the validation index, we roll back our chain to the last accumulator we have, and then re-validate them
Sourcefn find_best_chain(&self) -> BestChain
fn find_best_chain(&self) -> BestChain
Reconstructs the BestChain data based on the database indexes and headers. This is useful
to recover from an invalid state or data corruption
fn load_chain_state( chainstore: PersistedState, network: Network, assume_valid: AssumeValidArg, ) -> Result<ChainState<PersistedState>, BlockchainError>
Sourcepub fn open(
chainstore: PersistedState,
network: Network,
assume_valid: AssumeValidArg,
) -> Result<Self, BlockchainError>
pub fn open( chainstore: PersistedState, network: Network, assume_valid: AssumeValidArg, ) -> Result<Self, BlockchainError>
Opens an existing chain state or creates one from genesis if the store is uninitialized.
This is the main entry point for instantiating a ChainState. If the store already
has data, the state is loaded from it. Otherwise, the chain is initialized from the
genesis block for the given network.
§Errors
Returns an error if the store cannot be read or if the persisted state is corrupted.
Sourcefn check_db_integrity(&self) -> Result<(), BlockchainError>
fn check_db_integrity(&self) -> Result<(), BlockchainError>
Checks whether our database got a file-level corruption, and if so, reindex.
This protects us from fs corruption, like random bit-flips or power loss.
fn check_chain_integrity(&self) -> Result<(), BlockchainError>
Sourcefn deserialize_accumulator(
acc: Option<Vec<u8>>,
) -> Result<Stump, BlockchainError>
fn deserialize_accumulator( acc: Option<Vec<u8>>, ) -> Result<Stump, BlockchainError>
Tries to deserialize an accumulator returning an empty [Stump] acc is None
fn update_view( &self, height: u32, block: &BlockHeader, acc: Stump, ) -> Result<(), BlockchainError>
fn update_tip(&self, best_block: BlockHash, height: u32)
fn verify_script(&self, height: u32) -> Result<bool, PersistedState::Error>
pub fn acc(&self) -> Stump
Sourcefn get_next_required_work(
&self,
last_block: &BlockHeader,
next_height: u32,
next_header: &BlockHeader,
) -> Result<Target, BlockchainError>
fn get_next_required_work( &self, last_block: &BlockHeader, next_height: u32, next_header: &BlockHeader, ) -> Result<Target, BlockchainError>
Returns the next required work for the next block, usually it’s just the last block’s target but if we are in a retarget period, it’s calculated from the last 2016 blocks.
Sourcefn check_bip94_block(
&self,
block: &BlockHeader,
height: u32,
) -> Result<(), BlockchainError>
fn check_bip94_block( &self, block: &BlockHeader, height: u32, ) -> Result<(), BlockchainError>
Check timestamp against prev for difficulty-adjustment blocks to prevent timewarp attacks. Must only be called for non-genesis block headers.
Sourcepub fn validate_block_no_acc(
&self,
block: &Block,
height: u32,
inputs: HashMap<OutPoint, UtxoData>,
) -> Result<(), BlockchainError>
pub fn validate_block_no_acc( &self, block: &Block, height: u32, inputs: HashMap<OutPoint, UtxoData>, ) -> Result<(), BlockchainError>
Validates the block without checking whether the inputs are present in the UTXO set. This function contains the core validation logic.
The methods BlockchainInterface::validate_block and UpdatableChainstate::connect_block
call this and additionally verify the inclusion proof (i.e., they perform full validation).
Trait Implementations§
Source§impl<PersistedState: ChainStore> BlockchainInterface for ChainState<PersistedState>
impl<PersistedState: ChainStore> BlockchainInterface for ChainState<PersistedState>
type Error = BlockchainError
Source§fn get_params(&self) -> Params
fn get_params(&self) -> Params
Source§fn get_fork_point(&self, block: BlockHash) -> Result<BlockHash, Self::Error>
fn get_fork_point(&self, block: BlockHash) -> Result<BlockHash, Self::Error>
blockSource§fn update_acc(
&self,
acc: Stump,
block: &Block,
height: u32,
proof: Proof,
del_hashes: Vec<Hash>,
) -> Result<Stump, Self::Error>
fn update_acc( &self, acc: Stump, block: &Block, height: u32, proof: Proof, del_hashes: Vec<Hash>, ) -> Result<Stump, Self::Error>
Source§fn get_chain_tips(&self) -> Result<Vec<BlockHash>, Self::Error>
fn get_chain_tips(&self) -> Result<Vec<BlockHash>, Self::Error>
Source§fn validate_block(
&self,
block: &Block,
proof: Proof,
inputs: HashMap<OutPoint, UtxoData>,
del_hashes: Vec<Hash>,
acc: Stump,
) -> Result<(), Self::Error>
fn validate_block( &self, block: &Block, proof: Proof, inputs: HashMap<OutPoint, UtxoData>, del_hashes: Vec<Hash>, acc: Stump, ) -> Result<(), Self::Error>
Source§fn get_block_locator_for_tip(
&self,
tip: BlockHash,
) -> Result<Vec<BlockHash>, BlockchainError>
fn get_block_locator_for_tip( &self, tip: BlockHash, ) -> Result<Vec<BlockHash>, BlockchainError>
Source§fn get_block_height(&self, hash: &BlockHash) -> Result<Option<u32>, Self::Error>
fn get_block_height(&self, hash: &BlockHash) -> Result<Option<u32>, Self::Error>
Source§fn get_block_hash(&self, height: u32) -> Result<BlockHash, Self::Error>
fn get_block_hash(&self, height: u32) -> Result<BlockHash, Self::Error>
Source§fn get_tx(&self, _txid: &Txid) -> Result<Option<Transaction>, Self::Error>
fn get_tx(&self, _txid: &Txid) -> Result<Option<Transaction>, Self::Error>
bitcoin::Transaction] given its txid.Source§fn estimate_fee(&self, target: usize) -> Result<f64, Self::Error>
fn estimate_fee(&self, target: usize) -> Result<f64, Self::Error>
target blocks.Source§fn get_block(&self, _hash: &BlockHash) -> Result<Block, Self::Error>
fn get_block(&self, _hash: &BlockHash) -> Result<Block, Self::Error>
hash if any.Source§fn get_best_block(&self) -> Result<(u32, BlockHash), Self::Error>
fn get_best_block(&self) -> Result<(u32, BlockHash), Self::Error>
Source§fn get_block_header(&self, hash: &BlockHash) -> Result<BlockHeader, Self::Error>
fn get_block_header(&self, hash: &BlockHash) -> Result<BlockHeader, Self::Error>
hash