From ce2fb6ecb755114e2b7628f3024866f7f62d71fc Mon Sep 17 00:00:00 2001 From: Antioch Peverell <30642645+antiochp@users.noreply.github.com> Date: Thu, 22 Mar 2018 12:57:37 -0400 Subject: [PATCH] Rewind force rollback (#847) * rewind() vs rewind_readonly() * cleanup comments --- chain/src/chain.rs | 5 +---- chain/src/txhashset.rs | 35 ++++++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 83159f129..4335878dc 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -419,9 +419,7 @@ impl Chain { // against the latest block header. // We will rewind the extension internally to the pos for // the block header to ensure the view is consistent. - // Force rollback first as this is a "read-only" extension. txhashset::extending(&mut txhashset, |extension| { - extension.force_rollback(); extension.validate(&header, skip_rproofs) }) } @@ -471,8 +469,7 @@ impl Chain { let mut txhashset = self.txhashset.write().unwrap(); let merkle_proof = txhashset::extending(&mut txhashset, |extension| { - extension.force_rollback(); - extension.merkle_proof_via_rewind(output, block_header) + extension.merkle_proof(output, block_header) })?; Ok(merkle_proof) diff --git a/chain/src/txhashset.rs b/chain/src/txhashset.rs index fbe538ad7..ed787e0d3 100644 --- a/chain/src/txhashset.rs +++ b/chain/src/txhashset.rs @@ -471,19 +471,21 @@ impl<'a> Extension<'a> { /// Note: this relies on the MMR being stable even after pruning/compaction. /// We need the hash of each sibling pos from the pos up to the peak /// including the sibling leaf node which may have been removed. - pub fn merkle_proof_via_rewind( + pub fn merkle_proof( &mut self, output: &OutputIdentifier, block_header: &BlockHeader, ) -> Result { debug!( LOGGER, - "txhashset: merkle_proof_via_rewind: rewinding to block {:?}", + "txhashset: merkle_proof: output: {:?}, block: {:?}", + output.commit, block_header.hash() ); - // rewind to the specified block - self.rewind(block_header)?; + // rewind to the specified block and set the force_rollback flag (read-only) + self.rewind_readonly(block_header)?; + // then calculate the Merkle Proof based on the known pos let pos = self.get_output_pos(&output.commit)?; let merkle_proof = self.output_pmmr @@ -506,9 +508,25 @@ impl<'a> Extension<'a> { Ok(()) } + /// Rewinds the MMRs to the provided block, using the last output and + /// last kernel of the block we want to rewind to. + pub fn rewind_readonly(&mut self, block_header: &BlockHeader) -> Result<(), Error> { + // first make sure we set the rollback flag (read-only use of the extension) + self.force_rollback(); + + let hash = block_header.hash(); + let height = block_header.height; + debug!( + LOGGER, + "Rewinding (readonly) to header {} at {}", hash, height + ); + + self.rewind(block_header) + } + /// Rewinds the MMRs to the provided positions, given the output and /// kernel we want to rewind to. - pub fn rewind_pos( + fn rewind_pos( &mut self, height: u64, out_pos_rew: u64, @@ -553,9 +571,12 @@ impl<'a> Extension<'a> { /// Validate the txhashset state against the provided block header. /// Rewinds to that pos for the header first so we see a consistent /// view of the world. + /// Note: this is an expensive operation and sets force_rollback + /// so the extension is read-only. pub fn validate(&mut self, header: &BlockHeader, skip_rproofs: bool) -> Result<(), Error> { - // first rewind to the provided header - &self.rewind(header)?; + // first rewind to the provided header and + // set the force_rollback flag (read-only) + &self.rewind_readonly(header)?; // validate all hashes and sums within the trees if let Err(e) = self.output_pmmr.validate() {