Skip to content

Commit

Permalink
Reindex (mit-dci#48)
Browse files Browse the repository at this point in the history
* Reindex chain if we go in an undefined state

* Fix a bug during header download

If we stopped the daemon while it's running, we'ld get a corrupted
state, and header validation would loop forever
  • Loading branch information
Davidson-Souza authored May 20, 2023
1 parent ba4f5c0 commit f4f35af
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 27 deletions.
76 changes: 52 additions & 24 deletions src/blockchain/chain_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,22 +649,31 @@ impl<PersistedState: ChainStore> ChainState<PersistedState> {
}
Err(BlockchainError::BlockNotPresent)
}
// fn reindex_chain(chainstore: &KvChainStore, network: Network) -> BestChain {
// let mut height = 0;
// let mut hash = genesis_block(network).block_hash();
// while let Ok(Some(_hash)) = chainstore.get_block_hash(height) {
// height += 1;
// hash = _hash;
// }
// BestChain {
// best_block: hash,
// depth: height,
// validation_index: hash,
// rescan_index: None,
// alternative_tips: vec![],
// assume_valid_index: 0,
// }
// }
/// If we ever find ourselves in an undefined state, with one of our chain pointers
/// pointing to an invalid block, we'll find out what blocks do we have, and start from this
/// point.
fn reindex_chain(&self) -> BestChain {
let inner = read_lock!(self);

let mut height = 0;
let mut hash = inner
.chainstore
.get_block_hash(0)
.expect("No genesis block")
.unwrap();
while let Ok(Some(_hash)) = inner.chainstore.get_block_hash(height) {
height += 1;
hash = _hash;
}
BestChain {
best_block: hash,
depth: height,
validation_index: hash,
rescan_index: None,
alternative_tips: vec![],
assume_valid_index: 0,
}
}
pub fn load_chain_state(
chainstore: KvChainStore,
network: Network,
Expand All @@ -688,12 +697,15 @@ impl<PersistedState: ChainStore> ChainState<PersistedState> {
assume_valid: (Self::get_assume_valid_value(network, assume_valid_hash), 0),
};
info!(
"Chainstate loaded at height: {}",
"Chainstate loaded at height: {}, checking if we have all blocks",
inner.best_block.best_block
);
Ok(ChainState {
let chainstate = ChainState {
inner: RwLock::new(inner),
})
};
// Check the integrity of our chain
chainstate.reindex_chain();
Ok(chainstate)
}

fn load_acc<Storage: ChainStore>(data_storage: &Storage) -> Stump {
Expand Down Expand Up @@ -932,11 +944,22 @@ impl<PersistedState: ChainStore> BlockchainProviderInterface for ChainState<Pers
};
self.validate_block(block, height, inputs)?;
let acc = Self::update_acc(&self.acc(), block, height, proof, del_hashes)?;
let ibd = self.is_in_idb();
// ... If we came this far, we consider this block valid ...
if self.is_in_idb() && height % 10_000 == 0 {
info!("Downloading blocks at: {height}");
if ibd && height % 10_000 == 0 {
info!(
"Downloading blocks: height={height} hash={}",
block.block_hash()
);
self.flush()?;
}
if !ibd {
info!(
"New tip! hash={} height={height} tx_count={}",
block.block_hash(),
block.txdata.len()
)
}
// Notify others we have a new block
async_std::task::block_on(self.notify(Notification::NewBlock((block.to_owned(), height))));
self.update_view(height, &block.header, acc)?;
Expand All @@ -963,6 +986,9 @@ impl<PersistedState: ChainStore> BlockchainProviderInterface for ChainState<Pers
trace!("Accepting header {header:?}");
let _header = self.get_disk_block_header(&header.block_hash());
if _header.is_ok() {
if let DiskBlockHeader::HeadersOnly(header, height) = _header? {
self.update_tip(header.block_hash(), height);
}
return Ok(()); // We already have this header
}
let best_block = self.get_best_block()?;
Expand Down Expand Up @@ -999,9 +1025,11 @@ impl<PersistedState: ChainStore> BlockchainProviderInterface for ChainState<Pers
match header {
DiskBlockHeader::HeadersOnly(_, height) => Ok(height),
DiskBlockHeader::FullyValid(_, height) => Ok(height),
_ => unreachable!(
"Validation index is in an invalid state, you should re-index your node"
),
_ => {
self.reindex_chain();
log::error!("Validation index is in an invalid state, re-indexing chainstate");
Ok(0)
}
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/blockchain/p2p_blockchain/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use bitcoin::{
},
BlockHash, BlockHeader, Network, OutPoint, Transaction, TxOut, Txid,
};
use log::{error, info, warn};
use log::{error, info, trace, warn};
use rustreexo::accumulator::proof::Proof;
use std::{
collections::{HashMap, HashSet},
Expand Down Expand Up @@ -242,7 +242,7 @@ impl UtreexoNode {
return Ok(());
}
self.last_headers_request = Instant::now();
info!(
trace!(
"Downloading headers at: {} hash: {}",
self.chain.get_best_block()?.0,
headers[0].block_hash()
Expand Down Expand Up @@ -378,7 +378,6 @@ impl UtreexoNode {
mempool_delta
.extend(self._mempool.write().await.consume_block(&block.block));
}

match self.handle_block(block) {
Ok(_) => {}
Err(e) => {
Expand Down

0 comments on commit f4f35af

Please sign in to comment.