diff --git a/core/src/core/block.rs b/core/src/core/block.rs index e8f811a8d..ec0dc5267 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -431,9 +431,14 @@ impl Block { reward_kern: TxKernel, difficulty: Difficulty, ) -> Result { - // A block is just a big transaction, aggregate as such. Note that - // aggregate also runs validation and duplicate commitment checks. - let agg_tx = transaction::aggregate(txs, Some((reward_out, reward_kern)))?; + // A block is just a big transaction, aggregate as such. + // Note that aggregation also runs transaction validation + // and duplicate commitment checks. + let mut agg_tx = transaction::aggregate(txs)?; + // Now add the reward output and reward kernel to the aggregate tx. + // At this point the tx is technically invalid, + // but the tx body is valid if we account for the reward (i.e. as a block). + agg_tx = agg_tx.with_output(reward_out).with_kernel(reward_kern); // Now add the kernel offset of the previous block for a total let total_kernel_offset = @@ -452,6 +457,9 @@ impl Block { let now = Utc::now().timestamp(); let timestamp = DateTime::::from_utc(NaiveDateTime::from_timestamp(now, 0), Utc); + // Now build the block with all the above information. + // Note: We have not validated the block here. + // Caller must validate the block as necessary. Block { header: BlockHeader { height: prev.height + 1, diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 509dbe40b..d1cdf922d 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -613,8 +613,7 @@ impl Readable for Transaction { // Treat any validation issues as data corruption. // An example of this would be reading a tx // that exceeded the allowed number of inputs. - tx.validate_read(false) - .map_err(|_| ser::Error::CorruptedData)?; + tx.validate_read().map_err(|_| ser::Error::CorruptedData)?; Ok(tx) } @@ -749,23 +748,19 @@ impl Transaction { /// * rangeproof verification (on the body) /// * kernel signature verification (on the body) /// * kernel sum verification - pub fn validate_read(&self, with_reward: bool) -> Result<(), Error> { - self.body.validate_read(with_reward)?; - if !with_reward { - self.body.verify_features()?; - } + pub fn validate_read(&self) -> Result<(), Error> { + self.body.validate_read(false)?; + self.body.verify_features()?; Ok(()) } /// Validates all relevant parts of a fully built transaction. Checks the /// excess value against the signature as well as range proofs for each /// output. - pub fn validate(&self, with_reward: bool) -> Result<(), Error> { - self.body.validate(with_reward)?; - if !with_reward { - self.body.verify_features()?; - self.verify_kernel_sums(self.overage(), self.offset)?; - } + pub fn validate(&self) -> Result<(), Error> { + self.body.validate(false)?; + self.body.verify_features()?; + self.verify_kernel_sums(self.overage(), self.offset)?; Ok(()) } @@ -812,16 +807,13 @@ pub fn cut_through(inputs: &mut Vec, outputs: &mut Vec) -> Result Ok(()) } -/// Aggregate a vec of transactions into a multi-kernel transaction with -/// cut_through. Optionally allows passing a reward output and kernel for -/// block building. -pub fn aggregate( - mut transactions: Vec, - reward: Option<(Output, TxKernel)>, -) -> Result { +/// Aggregate a vec of txs into a multi-kernel tx with cut_through. +pub fn aggregate(mut txs: Vec) -> Result { // convenience short-circuiting - if reward.is_none() && transactions.len() == 1 { - return Ok(transactions.pop().unwrap()); + if txs.is_empty() { + return Ok(Transaction::empty()); + } else if txs.len() == 1 { + return Ok(txs.pop().unwrap()); } let mut inputs: Vec = vec![]; @@ -832,18 +824,13 @@ pub fn aggregate( // transaction let mut kernel_offsets: Vec = vec![]; - for mut transaction in transactions { + for mut tx in txs { // we will sum these later to give a single aggregate offset - kernel_offsets.push(transaction.offset); + kernel_offsets.push(tx.offset); - inputs.append(&mut transaction.body.inputs); - outputs.append(&mut transaction.body.outputs); - kernels.append(&mut transaction.body.kernels); - } - let with_reward = reward.is_some(); - if let Some((out, kernel)) = reward { - outputs.push(out); - kernels.push(kernel); + inputs.append(&mut tx.body.inputs); + outputs.append(&mut tx.body.outputs); + kernels.append(&mut tx.body.kernels); } // Sort inputs and outputs during cut_through. @@ -867,7 +854,7 @@ pub fn aggregate( // The resulting tx could be invalid for a variety of reasons - // * tx too large (too many inputs|outputs|kernels) // * cut-through may have invalidated the sums - tx.validate(with_reward)?; + tx.validate()?; Ok(tx) } @@ -883,7 +870,7 @@ pub fn deaggregate(mk_tx: Transaction, txs: Vec) -> Result) -> Result>) -> Result<(), PoolE stem_txs.len() ); - let agg_tx = transaction::aggregate(stem_txs, None)?; + let agg_tx = transaction::aggregate(stem_txs)?; let res = tx_pool.adapter.stem_tx_accepted(&agg_tx); if res.is_err() { @@ -142,7 +142,7 @@ fn process_fluff_phase(tx_pool: Arc>) -> Result<(), Pool stem_txs.len() ); - let agg_tx = transaction::aggregate(stem_txs, None)?; + let agg_tx = transaction::aggregate(stem_txs)?; let src = TxSource { debug_name: "fluff".to_string(), diff --git a/wallet/src/libtx/build.rs b/wallet/src/libtx/build.rs index b92f5a218..0e2c84b6a 100644 --- a/wallet/src/libtx/build.rs +++ b/wallet/src/libtx/build.rs @@ -299,7 +299,7 @@ mod test { &keychain, ).unwrap(); - tx.validate(false).unwrap(); + tx.validate().unwrap(); } #[test] @@ -319,7 +319,7 @@ mod test { &keychain, ).unwrap(); - tx.validate(false).unwrap(); + tx.validate().unwrap(); } #[test] @@ -333,6 +333,6 @@ mod test { &keychain, ).unwrap(); - tx.validate(false).unwrap(); + tx.validate().unwrap(); } } diff --git a/wallet/src/libtx/slate.rs b/wallet/src/libtx/slate.rs index 724807195..f1e54c646 100644 --- a/wallet/src/libtx/slate.rs +++ b/wallet/src/libtx/slate.rs @@ -398,7 +398,7 @@ impl Slate { final_tx.kernels()[0].verify()?; // confirm the overall transaction is valid (including the updated kernel) - let _ = final_tx.validate(false)?; + let _ = final_tx.validate()?; self.tx = final_tx; Ok(()) diff --git a/wallet/src/libwallet/internal/tx.rs b/wallet/src/libwallet/internal/tx.rs index 9f612bd6e..a721a7969 100644 --- a/wallet/src/libwallet/internal/tx.rs +++ b/wallet/src/libwallet/internal/tx.rs @@ -196,7 +196,7 @@ where // finalize the burn transaction and send let tx_burn = build::transaction(parts, &keychain)?; - tx_burn.validate(false)?; + tx_burn.validate()?; Ok(tx_burn) }