From 461b2d48531bac522ddb0b7eb532ebb70427f7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 19 Apr 2018 11:25:15 +0200 Subject: [PATCH] Fix receipts stripping. (#8414) --- ethcore/src/block.rs | 28 ++++++++++++++++++---------- ethcore/src/client/client.rs | 13 ++++++++++--- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index e3622c293..d9f3d27af 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -491,6 +491,24 @@ impl ClosedBlock { } impl LockedBlock { + + /// Removes outcomes from receipts and updates the receipt root. + /// + /// This is done after the block is enacted for historical reasons. + /// We allow inconsistency in receipts for some chains if `validate_receipts_transition` + /// is set to non-zero value, so the check only happens if we detect + /// unmatching root first and then fall back to striped receipts. + pub fn strip_receipts_outcomes(&mut self) { + for receipt in &mut self.block.receipts { + receipt.outcome = TransactionOutcome::Unknown; + } + self.block.header.set_receipts_root( + ordered_trie_root(self.block.receipts.iter().map(|r| r.rlp_bytes())) + ); + // compute hash and cache it. + self.block.header.compute_hash(); + } + /// Get the hash of the header without seal arguments. pub fn hash(&self) -> H256 { self.header().bare_hash() } @@ -570,7 +588,6 @@ fn enact( last_hashes: Arc, factories: Factories, is_epoch_begin: bool, - strip_receipts: bool, ) -> Result { { if ::log::max_log_level() >= ::log::LogLevel::Trace { @@ -600,12 +617,6 @@ fn enact( b.push_uncle(u)?; } - if strip_receipts { - for receipt in &mut b.block.receipts { - receipt.outcome = TransactionOutcome::Unknown; - } - } - Ok(b.close_and_lock()) } @@ -619,8 +630,6 @@ pub fn enact_verified( last_hashes: Arc, factories: Factories, is_epoch_begin: bool, - // Remove state root from transaction receipts to make them EIP-98 compatible. - strip_receipts: bool, ) -> Result { let view = view!(BlockView, &block.bytes); @@ -635,7 +644,6 @@ pub fn enact_verified( last_hashes, factories, is_epoch_begin, - strip_receipts, ) } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d2b63b6cd..bb7f5894b 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -415,7 +415,6 @@ impl Importer { let db = client.state_db.read().boxed_clone_canon(header.parent_hash()); let is_epoch_begin = chain.epoch_transition(parent.number(), *header.parent_hash()).is_some(); - let strip_receipts = header.number() < engine.params().validate_receipts_transition; let enact_result = enact_verified( block, engine, @@ -425,13 +424,21 @@ impl Importer { last_hashes, client.factories.clone(), is_epoch_begin, - strip_receipts, ); - let locked_block = enact_result.map_err(|e| { + let mut locked_block = enact_result.map_err(|e| { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); })?; + // Strip receipts for blocks before validate_receipts_transition, + // if the expected receipts root header does not match. + // (i.e. allow inconsistency in receipts outcome before the transition block) + if header.number() < engine.params().validate_receipts_transition + && header.receipts_root() != locked_block.block().header().receipts_root() + { + locked_block.strip_receipts_outcomes(); + } + // Final Verification if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) { warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);