diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 2aa80c9d0..4fedb62ff 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -30,8 +30,8 @@ use pipe; use store; use txhashset; use types::*; -use util::LOGGER; use util::secp::pedersen::{Commitment, RangeProof}; +use util::LOGGER; /// Orphan pool size is limited by MAX_ORPHAN_SIZE pub const MAX_ORPHAN_SIZE: usize = 200; @@ -460,25 +460,25 @@ impl Chain { txhashset.is_unspent(output_ref) } + fn next_block_height(&self) -> Result { + let bh = self.head_header()?; + Ok(bh.height + 1) + } + /// Validate a vector of "raw" transactions against the current chain state. pub fn validate_raw_txs( &self, txs: Vec, pre_tx: Option, ) -> Result, Error> { - let bh = self.head_header()?; + let height = self.next_block_height()?; let mut txhashset = self.txhashset.write().unwrap(); txhashset::extending_readonly(&mut txhashset, |extension| { - let valid_txs = extension.validate_raw_txs(txs, pre_tx, bh.height)?; + let valid_txs = extension.validate_raw_txs(txs, pre_tx, height)?; Ok(valid_txs) }) } - fn next_block_height(&self) -> Result { - let bh = self.head_header()?; - Ok(bh.height + 1) - } - /// Verify we are not attempting to spend a coinbase output /// that has not yet sufficiently matured. pub fn verify_coinbase_maturity(&self, tx: &Transaction) -> Result<(), Error> { diff --git a/chain/src/txhashset.rs b/chain/src/txhashset.rs index 6616b11cf..2081a01d5 100644 --- a/chain/src/txhashset.rs +++ b/chain/src/txhashset.rs @@ -422,25 +422,27 @@ impl<'a> Extension<'a> { let output_pos = self.output_pmmr.unpruned_size(); let kernel_pos = self.kernel_pmmr.unpruned_size(); + let rewind_to_height = height - 1; + // When applying blocks we can apply the coinbase output first // but we cannot do this here, so we need to apply outputs first. for ref output in &tx.outputs { if let Err(e) = self.apply_output(output) { - self.rewind_to_pos(output_pos, kernel_pos, height)?; + self.rewind_to_pos(output_pos, kernel_pos, rewind_to_height)?; return Err(e); } } for ref input in &tx.inputs { if let Err(e) = self.apply_input(input, height) { - self.rewind_to_pos(output_pos, kernel_pos, height)?; + self.rewind_to_pos(output_pos, kernel_pos, rewind_to_height)?; return Err(e); } } for ref kernel in &tx.kernels { if let Err(e) = self.apply_kernel(kernel) { - self.rewind_to_pos(output_pos, kernel_pos, height)?; + self.rewind_to_pos(output_pos, kernel_pos, rewind_to_height)?; return Err(e); } } @@ -474,13 +476,13 @@ impl<'a> Extension<'a> { let mut height = height; let mut valid_txs = vec![]; if let Some(tx) = pre_tx { - height += 1; self.apply_raw_tx(&tx, height)?; + height += 1; } for tx in txs { - height += 1; if self.apply_raw_tx(&tx, height).is_ok() { valid_txs.push(tx); + height += 1; } } Ok(valid_txs)