Skip to content

Commit cdd7cea

Browse files
fix: cannot find parent block during livesync (bnb-chain#111)
* fix: cannot find parent block during livesync * fix some test issues * fix some test issues * try to fix deadlock issue * try to fix dead loop issue * refine codes * fix an issue * fix issue & refactor * fix some review comments
1 parent 380dbb2 commit cdd7cea

19 files changed

Lines changed: 158 additions & 82 deletions

File tree

bin/reth/src/commands/debug_cmd/build_block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ impl Command {
279279
#[cfg(not(feature = "bsc"))]
280280
let executor = block_executor!(provider_factory.chain_spec()).executor(db);
281281

282-
let BlockExecutionOutput { state, receipts, requests, .. } =
283-
executor.execute((&block_with_senders.clone().unseal(), U256::MAX).into())?;
282+
let BlockExecutionOutput { state, receipts, requests, .. } = executor
283+
.execute((&block_with_senders.clone().unseal(), U256::MAX, None).into())?;
284284
let execution_outcome = ExecutionOutcome::new(
285285
state,
286286
receipts.into(),

bin/reth/src/commands/debug_cmd/in_memory_merkle.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ impl Command {
145145
.with_recovered_senders()
146146
.ok_or(BlockValidationError::SenderRecoveryError)?,
147147
merkle_block_td + block.difficulty,
148+
None,
148149
)
149150
.into(),
150151
)?;

bin/reth/src/commands/debug_cmd/merkle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl Command {
153153
provider_rw.static_file_provider().clone(),
154154
),
155155
));
156-
executor.execute_and_verify_one((&sealed_block.clone().unseal(), td).into())?;
156+
executor.execute_and_verify_one((&sealed_block.clone().unseal(), td, None).into())?;
157157
executor.finalize().write_to_storage(&provider_rw, None, OriginalValuesKnown::Yes)?;
158158

159159
let checkpoint = Some(StageCheckpoint::new(

crates/blockchain-tree/src/chain.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor};
1515
use reth_execution_errors::BlockExecutionError;
1616
use reth_execution_types::{Chain, ExecutionOutcome};
1717
use reth_primitives::{
18-
BlockHash, BlockNumber, ForkBlock, GotExpected, SealedBlockWithSenders, SealedHeader, U256,
18+
BlockHash, BlockNumber, ForkBlock, GotExpected, Header, SealedBlockWithSenders, SealedHeader,
19+
B256, U256,
1920
};
2021
use reth_provider::{
2122
providers::{BundleStateProvider, ConsistentDbView},
@@ -25,7 +26,7 @@ use reth_revm::database::StateProviderDatabase;
2526
use reth_trie::updates::TrieUpdates;
2627
use reth_trie_parallel::parallel_root::ParallelStateRoot;
2728
use std::{
28-
collections::BTreeMap,
29+
collections::{BTreeMap, HashMap},
2930
ops::{Deref, DerefMut},
3031
time::Instant,
3132
};
@@ -92,6 +93,7 @@ impl AppendableChain {
9293
let (bundle_state, trie_updates) = Self::validate_and_execute(
9394
block.clone(),
9495
parent_header,
96+
None,
9597
state_provider,
9698
externals,
9799
block_attachment,
@@ -138,6 +140,7 @@ impl AppendableChain {
138140
let (block_state, _) = Self::validate_and_execute(
139141
block.clone(),
140142
parent,
143+
None,
141144
bundle_state_data,
142145
externals,
143146
BlockAttachment::HistoricalFork,
@@ -170,6 +173,7 @@ impl AppendableChain {
170173
fn validate_and_execute<EDP, DB, E>(
171174
block: SealedBlockWithSenders,
172175
parent_block: &SealedHeader,
176+
ancestor_blocks: Option<&HashMap<B256, Header>>,
173177
bundle_state_data_provider: EDP,
174178
externals: &TreeExternals<DB, E>,
175179
block_attachment: BlockAttachment,
@@ -209,7 +213,7 @@ impl AppendableChain {
209213
let block_hash = block.hash();
210214
let block = block.unseal();
211215

212-
let state = executor.execute((&block, U256::MAX).into())?;
216+
let state = executor.execute((&block, U256::MAX, ancestor_blocks).into())?;
213217
let BlockExecutionOutput { state, receipts, requests, .. } = state;
214218
externals
215219
.consensus
@@ -285,6 +289,9 @@ impl AppendableChain {
285289
{
286290
let parent_block = self.chain.tip();
287291

292+
let ancestor_blocks =
293+
self.headers().map(|h| return (h.hash() as B256, h.header().clone())).collect();
294+
288295
let bundle_state_data = BundleStateDataRef {
289296
execution_outcome: self.execution_outcome(),
290297
sidechain_block_hashes: &side_chain_block_hashes,
@@ -295,6 +302,7 @@ impl AppendableChain {
295302
let (block_state, _) = Self::validate_and_execute(
296303
block.clone(),
297304
parent_block,
305+
Some(&ancestor_blocks),
298306
bundle_state_data,
299307
externals,
300308
block_attachment,

crates/bsc/engine/src/task.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub(crate) struct ParliaEngineTask<
6161
> {
6262
/// The configured chain spec
6363
chain_spec: Arc<ChainSpec>,
64-
/// The coneensus instance
64+
/// The consensus instance
6565
consensus: Parlia,
6666
/// The provider used to read the block and header from the inserted chain
6767
provider: Provider,

crates/bsc/evm/src/execute.rs

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,15 @@ where
323323
&mut self,
324324
block: &BlockWithSenders,
325325
total_difficulty: U256,
326+
ancestor: Option<&HashMap<B256, Header>>,
326327
) -> Result<BscExecuteOutput, BlockExecutionError> {
327328
// 1. get parent header and snapshot
328-
let parent = &(self.get_header_by_hash(block.parent_hash)?);
329+
let parent = &(self.get_header_by_hash(block.parent_hash, ancestor)?);
329330
let snapshot_reader = SnapshotReader::new(self.provider.clone(), self.parlia.clone());
330-
let snap = &(snapshot_reader.snapshot(parent, None)?);
331+
let snap = &(snapshot_reader.snapshot(parent, ancestor)?);
331332

332333
// 2. prepare state on new block
333-
self.on_new_block(&block.header, parent, snap)?;
334+
self.on_new_block(&block.header, parent, ancestor, snap)?;
334335

335336
// 3. get data from contracts before execute transactions
336337
let post_execution_input =
@@ -353,6 +354,7 @@ where
353354
self.post_execution(
354355
block,
355356
parent,
357+
ancestor,
356358
snap,
357359
post_execution_input,
358360
&mut system_txs,
@@ -370,6 +372,7 @@ where
370372

371373
pub(crate) fn get_justified_header(
372374
&self,
375+
ancestor: Option<&HashMap<B256, Header>>,
373376
snap: &Snapshot,
374377
) -> Result<Header, BlockExecutionError> {
375378
if snap.vote_data.source_hash == B256::ZERO && snap.vote_data.target_hash == B256::ZERO {
@@ -382,16 +385,23 @@ where
382385
});
383386
}
384387

385-
self.get_header_by_hash(snap.vote_data.target_hash)
388+
self.get_header_by_hash(snap.vote_data.target_hash, ancestor)
386389
}
387390

388391
pub(crate) fn get_header_by_hash(
389392
&self,
390393
block_hash: B256,
394+
ancestor: Option<&HashMap<B256, Header>>,
391395
) -> Result<Header, BlockExecutionError> {
392-
self.provider
393-
.header(&block_hash)
394-
.map_err(|err| BscBlockExecutionError::ProviderInnerError { error: err.into() })?
396+
ancestor
397+
.and_then(|m| m.get(&block_hash).cloned())
398+
.or_else(|| {
399+
self.provider
400+
.header(&block_hash)
401+
.map_err(|err| BscBlockExecutionError::ProviderInnerError { error: err.into() })
402+
.ok()
403+
.flatten()
404+
})
395405
.ok_or_else(|| BscBlockExecutionError::UnknownHeader { block_hash }.into())
396406
}
397407

@@ -670,7 +680,7 @@ where
670680
DB: Database<Error: Into<ProviderError> + std::fmt::Display>,
671681
P: ParliaProvider,
672682
{
673-
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
683+
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders, Header>;
674684
type Output = BlockExecutionOutput<Receipt>;
675685
type Error = BlockExecutionError;
676686

@@ -682,9 +692,9 @@ where
682692
///
683693
/// State changes are committed to the database.
684694
fn execute(mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
685-
let BlockExecutionInput { block, total_difficulty } = input;
695+
let BlockExecutionInput { block, total_difficulty, ancestor_headers } = input;
686696
let BscExecuteOutput { receipts, gas_used, snapshot } =
687-
self.execute_and_verify(block, total_difficulty)?;
697+
self.execute_and_verify(block, total_difficulty, ancestor_headers)?;
688698

689699
// NOTE: we need to merge keep the reverts for the bundle retention
690700
self.state.merge_transitions(BundleRetention::Reverts);
@@ -726,15 +736,15 @@ where
726736
DB: Database<Error: Into<ProviderError> + std::fmt::Display>,
727737
P: ParliaProvider,
728738
{
729-
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
739+
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders, Header>;
730740
type Output = ExecutionOutcome;
731741
type Error = BlockExecutionError;
732742

733743
fn execute_and_verify_one(&mut self, input: Self::Input<'_>) -> Result<(), Self::Error> {
734-
let BlockExecutionInput { block, total_difficulty } = input;
744+
let BlockExecutionInput { block, total_difficulty, .. } = input;
735745
let execute_start = Instant::now();
736746
let BscExecuteOutput { receipts, gas_used: _, snapshot } =
737-
self.executor.execute_and_verify(block, total_difficulty)?;
747+
self.executor.execute_and_verify(block, total_difficulty, None)?;
738748
self.stats.execution_duration += execute_start.elapsed();
739749

740750
validate_block_post_execution(block, self.executor.chain_spec(), &receipts)?;
@@ -806,7 +816,7 @@ where
806816
pub fn snapshot(
807817
&self,
808818
header: &Header,
809-
parent: Option<&Header>,
819+
ancestor: Option<&HashMap<B256, Header>>,
810820
) -> Result<Snapshot, BlockExecutionError> {
811821
let mut cache = RECENT_SNAPS.write();
812822

@@ -853,14 +863,14 @@ where
853863

854864
// No snapshot for this header, gather the header and move backward
855865
skip_headers.push(header.clone());
856-
if let Some(parent) = parent {
857-
block_number = parent.number;
858-
block_hash = header.parent_hash;
859-
header = parent.clone();
860-
} else if let Ok(h) = self.get_header_by_hash(header.parent_hash) {
866+
if let Ok(h) = self.get_header_by_hash(header.parent_hash, ancestor) {
861867
block_number = h.number;
862868
block_hash = header.parent_hash;
863869
header = h;
870+
} else {
871+
return Err(
872+
BscBlockExecutionError::UnknownHeader { block_hash: header.parent_hash }.into()
873+
)
864874
}
865875
}
866876

@@ -880,7 +890,7 @@ where
880890
{
881891
// change validator set
882892
let checkpoint_header =
883-
self.find_ancient_header(header, snap.miner_history_check_len())?;
893+
self.find_ancient_header(header, ancestor, snap.miner_history_check_len())?;
884894

885895
let validators_info = self
886896
.parlia
@@ -924,21 +934,32 @@ where
924934
Ok(snap)
925935
}
926936

927-
fn get_header_by_hash(&self, block_hash: B256) -> Result<Header, BlockExecutionError> {
928-
self.provider
929-
.header(&block_hash)
930-
.map_err(|err| BscBlockExecutionError::ProviderInnerError { error: err.into() })?
937+
fn get_header_by_hash(
938+
&self,
939+
block_hash: B256,
940+
ancestor: Option<&HashMap<B256, Header>>,
941+
) -> Result<Header, BlockExecutionError> {
942+
ancestor
943+
.and_then(|m| m.get(&block_hash).cloned())
944+
.or_else(|| {
945+
self.provider
946+
.header(&block_hash)
947+
.map_err(|err| BscBlockExecutionError::ProviderInnerError { error: err.into() })
948+
.ok()
949+
.flatten()
950+
})
931951
.ok_or_else(|| BscBlockExecutionError::UnknownHeader { block_hash }.into())
932952
}
933953

934954
fn find_ancient_header(
935955
&self,
936956
header: &Header,
957+
ancestor: Option<&HashMap<B256, Header>>,
937958
count: u64,
938959
) -> Result<Header, BlockExecutionError> {
939960
let mut result = header.clone();
940961
for _ in 0..count {
941-
result = self.get_header_by_hash(result.parent_hash)?;
962+
result = self.get_header_by_hash(result.parent_hash, ancestor)?;
942963
}
943964
Ok(result)
944965
}

crates/bsc/evm/src/post_execution.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use reth_primitives::{
1212
hex,
1313
parlia::{Snapshot, VoteAddress, VoteAttestation},
1414
system_contracts::SYSTEM_REWARD_CONTRACT,
15-
Address, BlockWithSenders, GotExpected, Header, Receipt, TransactionSigned, U256,
15+
Address, BlockWithSenders, GotExpected, Header, Receipt, TransactionSigned, B256, U256,
1616
};
1717
use reth_provider::ParliaProvider;
1818
use reth_revm::bsc::SYSTEM_ADDRESS;
@@ -41,6 +41,7 @@ where
4141
&mut self,
4242
block: &BlockWithSenders,
4343
parent: &Header,
44+
ancestor: Option<&HashMap<B256, Header>>,
4445
snap: &Snapshot,
4546
post_execution_input: PostExecutionInput,
4647
system_txs: &mut Vec<TransactionSigned>,
@@ -107,6 +108,7 @@ where
107108
if self.chain_spec().is_plato_active_at_block(number) {
108109
self.distribute_finality_reward(
109110
header,
111+
ancestor,
110112
system_txs,
111113
receipts,
112114
cumulative_gas_used,
@@ -369,6 +371,7 @@ where
369371
fn distribute_finality_reward(
370372
&mut self,
371373
header: &Header,
374+
ancestor: Option<&HashMap<B256, Header>>,
372375
system_txs: &mut Vec<TransactionSigned>,
373376
receipts: &mut Vec<Receipt>,
374377
cumulative_gas_used: &mut u64,
@@ -385,14 +388,14 @@ where
385388
let end = header.number;
386389
let mut target_hash = header.parent_hash;
387390
for _ in (start..end).rev() {
388-
let header = &(self.get_header_by_hash(target_hash)?);
391+
let header = &(self.get_header_by_hash(target_hash, ancestor)?);
389392

390393
if let Some(attestation) =
391394
self.parlia().get_vote_attestation_from_header(header).map_err(|err| {
392395
BscBlockExecutionError::ParliaConsensusInnerError { error: err.into() }
393396
})?
394397
{
395-
self.process_attestation(&attestation, header, &mut accumulated_weights)?;
398+
self.process_attestation(&attestation, header, ancestor, &mut accumulated_weights)?;
396399
}
397400

398401
target_hash = header.parent_hash;
@@ -445,10 +448,11 @@ where
445448
&self,
446449
attestation: &VoteAttestation,
447450
parent_header: &Header,
451+
ancestor: Option<&HashMap<B256, Header>>,
448452
accumulated_weights: &mut HashMap<Address, U256>,
449453
) -> Result<(), BlockExecutionError> {
450-
let justified_header = self.get_header_by_hash(attestation.data.target_hash)?;
451-
let parent = self.get_header_by_hash(justified_header.parent_hash)?;
454+
let justified_header = self.get_header_by_hash(attestation.data.target_hash, ancestor)?;
455+
let parent = self.get_header_by_hash(justified_header.parent_hash, ancestor)?;
452456
let snapshot_reader = SnapshotReader::new(self.provider.clone(), self.parlia.clone());
453457
let snapshot = &(snapshot_reader.snapshot(&parent, None)?);
454458
let validators = &snapshot.validators;

0 commit comments

Comments
 (0)