mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 03:21:08 +03:00
[PIBD] Fix to restart of PIBD download on corrupted data or mismatched roots (#3775)
* process restart * remove trace statements * remove further debug statement * remove further debug statement
This commit is contained in:
parent
213dfd4f19
commit
05ec6fda38
2 changed files with 55 additions and 14 deletions
|
@ -158,7 +158,7 @@ pub struct Chain {
|
||||||
pow_verifier: fn(&BlockHeader) -> Result<(), pow::Error>,
|
pow_verifier: fn(&BlockHeader) -> Result<(), pow::Error>,
|
||||||
denylist: Arc<RwLock<Vec<Hash>>>,
|
denylist: Arc<RwLock<Vec<Hash>>>,
|
||||||
archive_mode: bool,
|
archive_mode: bool,
|
||||||
genesis: BlockHeader,
|
genesis: Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chain {
|
impl Chain {
|
||||||
|
@ -184,7 +184,7 @@ impl Chain {
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
setup_head(&genesis, &store, &mut header_pmmr, &mut txhashset)?;
|
setup_head(&genesis, &store, &mut header_pmmr, &mut txhashset, false)?;
|
||||||
|
|
||||||
// Initialize the output_pos index based on UTXO set
|
// Initialize the output_pos index based on UTXO set
|
||||||
// and NRD kernel_pos index based recent kernel history.
|
// and NRD kernel_pos index based recent kernel history.
|
||||||
|
@ -207,7 +207,7 @@ impl Chain {
|
||||||
pow_verifier,
|
pow_verifier,
|
||||||
denylist: Arc::new(RwLock::new(vec![])),
|
denylist: Arc::new(RwLock::new(vec![])),
|
||||||
archive_mode,
|
archive_mode,
|
||||||
genesis: genesis.header,
|
genesis: genesis,
|
||||||
};
|
};
|
||||||
|
|
||||||
chain.log_heads()?;
|
chain.log_heads()?;
|
||||||
|
@ -269,6 +269,33 @@ impl Chain {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// wipes the chain head down to genesis, without attempting to rewind
|
||||||
|
/// Used upon PIBD failure, where we want to keep the header chain but
|
||||||
|
/// restart the output PMMRs from scratch
|
||||||
|
pub fn reset_chain_head_to_genesis(&self) -> Result<(), Error> {
|
||||||
|
let mut header_pmmr = self.header_pmmr.write();
|
||||||
|
let mut txhashset = self.txhashset.write();
|
||||||
|
let batch = self.store.batch()?;
|
||||||
|
|
||||||
|
// Change head back to genesis
|
||||||
|
{
|
||||||
|
let head = Tip::from_header(&self.genesis.header);
|
||||||
|
batch.save_body_head(&head)?;
|
||||||
|
batch.commit()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinit
|
||||||
|
setup_head(
|
||||||
|
&self.genesis,
|
||||||
|
&self.store,
|
||||||
|
&mut header_pmmr,
|
||||||
|
&mut txhashset,
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Reset prune lists (when PIBD resets and rolls back the
|
/// Reset prune lists (when PIBD resets and rolls back the
|
||||||
/// entire chain, the prune list needs to be manually wiped
|
/// entire chain, the prune list needs to be manually wiped
|
||||||
/// as it's currently not included as part of rewind)
|
/// as it's currently not included as part of rewind)
|
||||||
|
@ -309,7 +336,7 @@ impl Chain {
|
||||||
|
|
||||||
/// return genesis header
|
/// return genesis header
|
||||||
pub fn genesis(&self) -> BlockHeader {
|
pub fn genesis(&self) -> BlockHeader {
|
||||||
self.genesis.clone()
|
self.genesis.header.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shared store instance.
|
/// Shared store instance.
|
||||||
|
@ -703,7 +730,7 @@ impl Chain {
|
||||||
txhashset::extending_readonly(&mut header_pmmr, &mut txhashset, |ext, batch| {
|
txhashset::extending_readonly(&mut header_pmmr, &mut txhashset, |ext, batch| {
|
||||||
self.rewind_and_apply_fork(&header, ext, batch)?;
|
self.rewind_and_apply_fork(&header, ext, batch)?;
|
||||||
ext.extension.validate(
|
ext.extension.validate(
|
||||||
&self.genesis,
|
&self.genesis.header,
|
||||||
fast_validation,
|
fast_validation,
|
||||||
&NoStatus,
|
&NoStatus,
|
||||||
None,
|
None,
|
||||||
|
@ -943,7 +970,7 @@ impl Chain {
|
||||||
self.txhashset(),
|
self.txhashset(),
|
||||||
self.header_pmmr.clone(),
|
self.header_pmmr.clone(),
|
||||||
header.clone(),
|
header.clone(),
|
||||||
self.genesis.clone(),
|
self.genesis.header.clone(),
|
||||||
self.store.clone(),
|
self.store.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -1125,7 +1152,13 @@ impl Chain {
|
||||||
|
|
||||||
let header_pmmr = self.header_pmmr.read();
|
let header_pmmr = self.header_pmmr.read();
|
||||||
let batch = self.store.batch()?;
|
let batch = self.store.batch()?;
|
||||||
txhashset.verify_kernel_pos_index(&self.genesis, &header_pmmr, &batch, None, None)?;
|
txhashset.verify_kernel_pos_index(
|
||||||
|
&self.genesis.header,
|
||||||
|
&header_pmmr,
|
||||||
|
&batch,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all good, prepare a new batch and update all the required records
|
// all good, prepare a new batch and update all the required records
|
||||||
|
@ -1143,8 +1176,15 @@ impl Chain {
|
||||||
|
|
||||||
// Validate the extension, generating the utxo_sum and kernel_sum.
|
// Validate the extension, generating the utxo_sum and kernel_sum.
|
||||||
// Full validation, including rangeproofs and kernel signature verification.
|
// Full validation, including rangeproofs and kernel signature verification.
|
||||||
let (utxo_sum, kernel_sum) =
|
let (utxo_sum, kernel_sum) = extension.validate(
|
||||||
extension.validate(&self.genesis, false, status, None, None, &header, None)?;
|
&self.genesis.header,
|
||||||
|
false,
|
||||||
|
status,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
&header,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Save the block_sums (utxo_sum, kernel_sum) to the db for use later.
|
// Save the block_sums (utxo_sum, kernel_sum) to the db for use later.
|
||||||
batch.save_block_sums(
|
batch.save_block_sums(
|
||||||
|
@ -1231,7 +1271,7 @@ impl Chain {
|
||||||
|
|
||||||
let tail = match batch.tail() {
|
let tail = match batch.tail() {
|
||||||
Ok(tail) => tail,
|
Ok(tail) => tail,
|
||||||
Err(_) => Tip::from_header(&self.genesis),
|
Err(_) => Tip::from_header(&self.genesis.header),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cutoff = head.height.saturating_sub(horizon);
|
let mut cutoff = head.height.saturating_sub(horizon);
|
||||||
|
@ -1643,6 +1683,7 @@ fn setup_head(
|
||||||
store: &store::ChainStore,
|
store: &store::ChainStore,
|
||||||
header_pmmr: &mut txhashset::PMMRHandle<BlockHeader>,
|
header_pmmr: &mut txhashset::PMMRHandle<BlockHeader>,
|
||||||
txhashset: &mut txhashset::TxHashSet,
|
txhashset: &mut txhashset::TxHashSet,
|
||||||
|
resetting_pibd: bool,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut batch = store.batch()?;
|
let mut batch = store.batch()?;
|
||||||
|
|
||||||
|
@ -1689,7 +1730,7 @@ fn setup_head(
|
||||||
let head = batch.get_block_header(&head.last_block_h)?;
|
let head = batch.get_block_header(&head.last_block_h)?;
|
||||||
let pibd_tip = store.pibd_head()?;
|
let pibd_tip = store.pibd_head()?;
|
||||||
let pibd_head = batch.get_block_header(&pibd_tip.last_block_h)?;
|
let pibd_head = batch.get_block_header(&pibd_tip.last_block_h)?;
|
||||||
if pibd_head.height > head.height {
|
if pibd_head.height > head.height && !resetting_pibd {
|
||||||
pibd_in_progress = true;
|
pibd_in_progress = true;
|
||||||
pibd_head
|
pibd_head
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -111,12 +111,12 @@ impl StateSync {
|
||||||
if let Some(d) = desegmenter.write().as_mut() {
|
if let Some(d) = desegmenter.write().as_mut() {
|
||||||
d.reset();
|
d.reset();
|
||||||
};
|
};
|
||||||
if let Err(e) = self.chain.reset_chain_head(self.chain.genesis(), false) {
|
|
||||||
error!("pibd_sync restart: chain reset error = {}", e);
|
|
||||||
}
|
|
||||||
if let Err(e) = self.chain.reset_pibd_head() {
|
if let Err(e) = self.chain.reset_pibd_head() {
|
||||||
error!("pibd_sync restart: reset pibd_head error = {}", e);
|
error!("pibd_sync restart: reset pibd_head error = {}", e);
|
||||||
}
|
}
|
||||||
|
if let Err(e) = self.chain.reset_chain_head_to_genesis() {
|
||||||
|
error!("pibd_sync restart: chain reset to genesis error = {}", e);
|
||||||
|
}
|
||||||
if let Err(e) = self.chain.reset_prune_lists() {
|
if let Err(e) = self.chain.reset_prune_lists() {
|
||||||
error!("pibd_sync restart: reset prune lists error = {}", e);
|
error!("pibd_sync restart: reset prune lists error = {}", e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue