Skip to content

Commit 05ec6fd

Browse files
authored
[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
1 parent 213dfd4 commit 05ec6fd

File tree

2 files changed

+55
-14
lines changed

2 files changed

+55
-14
lines changed

chain/src/chain.rs

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ pub struct Chain {
158158
pow_verifier: fn(&BlockHeader) -> Result<(), pow::Error>,
159159
denylist: Arc<RwLock<Vec<Hash>>>,
160160
archive_mode: bool,
161-
genesis: BlockHeader,
161+
genesis: Block,
162162
}
163163

164164
impl Chain {
@@ -184,7 +184,7 @@ impl Chain {
184184
None,
185185
)?;
186186

187-
setup_head(&genesis, &store, &mut header_pmmr, &mut txhashset)?;
187+
setup_head(&genesis, &store, &mut header_pmmr, &mut txhashset, false)?;
188188

189189
// Initialize the output_pos index based on UTXO set
190190
// and NRD kernel_pos index based recent kernel history.
@@ -207,7 +207,7 @@ impl Chain {
207207
pow_verifier,
208208
denylist: Arc::new(RwLock::new(vec![])),
209209
archive_mode,
210-
genesis: genesis.header,
210+
genesis: genesis,
211211
};
212212

213213
chain.log_heads()?;
@@ -269,6 +269,33 @@ impl Chain {
269269
Ok(())
270270
}
271271

272+
/// wipes the chain head down to genesis, without attempting to rewind
273+
/// Used upon PIBD failure, where we want to keep the header chain but
274+
/// restart the output PMMRs from scratch
275+
pub fn reset_chain_head_to_genesis(&self) -> Result<(), Error> {
276+
let mut header_pmmr = self.header_pmmr.write();
277+
let mut txhashset = self.txhashset.write();
278+
let batch = self.store.batch()?;
279+
280+
// Change head back to genesis
281+
{
282+
let head = Tip::from_header(&self.genesis.header);
283+
batch.save_body_head(&head)?;
284+
batch.commit()?;
285+
}
286+
287+
// Reinit
288+
setup_head(
289+
&self.genesis,
290+
&self.store,
291+
&mut header_pmmr,
292+
&mut txhashset,
293+
true,
294+
)?;
295+
296+
Ok(())
297+
}
298+
272299
/// Reset prune lists (when PIBD resets and rolls back the
273300
/// entire chain, the prune list needs to be manually wiped
274301
/// as it's currently not included as part of rewind)
@@ -309,7 +336,7 @@ impl Chain {
309336

310337
/// return genesis header
311338
pub fn genesis(&self) -> BlockHeader {
312-
self.genesis.clone()
339+
self.genesis.header.clone()
313340
}
314341

315342
/// Shared store instance.
@@ -703,7 +730,7 @@ impl Chain {
703730
txhashset::extending_readonly(&mut header_pmmr, &mut txhashset, |ext, batch| {
704731
self.rewind_and_apply_fork(&header, ext, batch)?;
705732
ext.extension.validate(
706-
&self.genesis,
733+
&self.genesis.header,
707734
fast_validation,
708735
&NoStatus,
709736
None,
@@ -943,7 +970,7 @@ impl Chain {
943970
self.txhashset(),
944971
self.header_pmmr.clone(),
945972
header.clone(),
946-
self.genesis.clone(),
973+
self.genesis.header.clone(),
947974
self.store.clone(),
948975
))
949976
}
@@ -1125,7 +1152,13 @@ impl Chain {
11251152

11261153
let header_pmmr = self.header_pmmr.read();
11271154
let batch = self.store.batch()?;
1128-
txhashset.verify_kernel_pos_index(&self.genesis, &header_pmmr, &batch, None, None)?;
1155+
txhashset.verify_kernel_pos_index(
1156+
&self.genesis.header,
1157+
&header_pmmr,
1158+
&batch,
1159+
None,
1160+
None,
1161+
)?;
11291162
}
11301163

11311164
// all good, prepare a new batch and update all the required records
@@ -1143,8 +1176,15 @@ impl Chain {
11431176

11441177
// Validate the extension, generating the utxo_sum and kernel_sum.
11451178
// Full validation, including rangeproofs and kernel signature verification.
1146-
let (utxo_sum, kernel_sum) =
1147-
extension.validate(&self.genesis, false, status, None, None, &header, None)?;
1179+
let (utxo_sum, kernel_sum) = extension.validate(
1180+
&self.genesis.header,
1181+
false,
1182+
status,
1183+
None,
1184+
None,
1185+
&header,
1186+
None,
1187+
)?;
11481188

11491189
// Save the block_sums (utxo_sum, kernel_sum) to the db for use later.
11501190
batch.save_block_sums(
@@ -1231,7 +1271,7 @@ impl Chain {
12311271

12321272
let tail = match batch.tail() {
12331273
Ok(tail) => tail,
1234-
Err(_) => Tip::from_header(&self.genesis),
1274+
Err(_) => Tip::from_header(&self.genesis.header),
12351275
};
12361276

12371277
let mut cutoff = head.height.saturating_sub(horizon);
@@ -1643,6 +1683,7 @@ fn setup_head(
16431683
store: &store::ChainStore,
16441684
header_pmmr: &mut txhashset::PMMRHandle<BlockHeader>,
16451685
txhashset: &mut txhashset::TxHashSet,
1686+
resetting_pibd: bool,
16461687
) -> Result<(), Error> {
16471688
let mut batch = store.batch()?;
16481689

@@ -1689,7 +1730,7 @@ fn setup_head(
16891730
let head = batch.get_block_header(&head.last_block_h)?;
16901731
let pibd_tip = store.pibd_head()?;
16911732
let pibd_head = batch.get_block_header(&pibd_tip.last_block_h)?;
1692-
if pibd_head.height > head.height {
1733+
if pibd_head.height > head.height && !resetting_pibd {
16931734
pibd_in_progress = true;
16941735
pibd_head
16951736
} else {

servers/src/grin/sync/state_sync.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@ impl StateSync {
111111
if let Some(d) = desegmenter.write().as_mut() {
112112
d.reset();
113113
};
114-
if let Err(e) = self.chain.reset_chain_head(self.chain.genesis(), false) {
115-
error!("pibd_sync restart: chain reset error = {}", e);
116-
}
117114
if let Err(e) = self.chain.reset_pibd_head() {
118115
error!("pibd_sync restart: reset pibd_head error = {}", e);
119116
}
117+
if let Err(e) = self.chain.reset_chain_head_to_genesis() {
118+
error!("pibd_sync restart: chain reset to genesis error = {}", e);
119+
}
120120
if let Err(e) = self.chain.reset_prune_lists() {
121121
error!("pibd_sync restart: reset prune lists error = {}", e);
122122
}

0 commit comments

Comments
 (0)