From 50ce7ba0433e916ddf6154ff64bdd987bd0e68c2 Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Fri, 1 Nov 2019 10:56:58 +0000 Subject: [PATCH] Refactor transaction building combinators (#3057) * tx combinators now take operate on Result to allow for more robust errors handling replace with_fee() and with_lock_height() with a more flexible with_features() * pass kernel features in as arg to build::transaction() * fix chain tests * fix pool tests * do not pass kernel around in the combinators just set it once on the tx when building * build::partial_transaction now takes a existing tx to build on --- chain/tests/mine_simple_chain.rs | 6 +- chain/tests/test_coinbase_maturity.rs | 5 +- core/src/core/transaction.rs | 56 ++++----- core/src/libtx/build.rs | 175 ++++++++++---------------- core/src/libtx/error.rs | 3 + core/tests/block.rs | 28 ++--- core/tests/common.rs | 29 ++--- core/tests/core.rs | 57 ++++----- pool/tests/common.rs | 21 +++- 9 files changed, 155 insertions(+), 225 deletions(-) diff --git a/chain/tests/mine_simple_chain.rs b/chain/tests/mine_simple_chain.rs index 506201faa..05657f92e 100644 --- a/chain/tests/mine_simple_chain.rs +++ b/chain/tests/mine_simple_chain.rs @@ -16,7 +16,7 @@ use self::chain::types::{NoopAdapter, Tip}; use self::chain::Chain; use self::core::core::hash::Hashed; use self::core::core::verifier_cache::LruVerifierCache; -use self::core::core::{Block, BlockHeader, OutputIdentifier, Transaction}; +use self::core::core::{Block, BlockHeader, KernelFeatures, OutputIdentifier, Transaction}; use self::core::global::ChainTypes; use self::core::libtx::{self, build, ProofBuilder}; use self::core::pow::Difficulty; @@ -562,10 +562,10 @@ fn spend_in_fork_and_compact() { let key_id31 = ExtKeychainPath::new(1, 31, 0, 0, 0).to_identifier(); let tx1 = build::transaction( + KernelFeatures::Plain { fee: 20000 }, vec![ build::coinbase_input(consensus::REWARD, key_id2.clone()), build::output(consensus::REWARD - 20000, key_id30.clone()), - build::with_fee(20000), ], &kc, &pb, @@ -580,10 +580,10 @@ fn spend_in_fork_and_compact() { chain.validate(false).unwrap(); let tx2 = build::transaction( + KernelFeatures::Plain { fee: 20000 }, vec![ build::input(consensus::REWARD - 20000, key_id30.clone()), build::output(consensus::REWARD - 40000, key_id31.clone()), - build::with_fee(20000), ], &kc, &pb, diff --git a/chain/tests/test_coinbase_maturity.rs b/chain/tests/test_coinbase_maturity.rs index 4f3a2c4da..a4748b23e 100644 --- a/chain/tests/test_coinbase_maturity.rs +++ b/chain/tests/test_coinbase_maturity.rs @@ -15,6 +15,7 @@ use self::chain::types::NoopAdapter; use self::chain::ErrorKind; use self::core::core::verifier_cache::LruVerifierCache; +use self::core::core::KernelFeatures; use self::core::global::{self, ChainTypes}; use self::core::libtx::{self, build, ProofBuilder}; use self::core::pow::Difficulty; @@ -99,10 +100,10 @@ fn test_coinbase_maturity() { // here we build a tx that attempts to spend the earlier coinbase output // this is not a valid tx as the coinbase output cannot be spent yet let coinbase_txn = build::transaction( + KernelFeatures::Plain { fee: 2 }, vec![ build::coinbase_input(amount, key_id1.clone()), build::output(amount - 2, key_id2.clone()), - build::with_fee(2), ], &keychain, &builder, @@ -182,10 +183,10 @@ fn test_coinbase_maturity() { // here we build a tx that attempts to spend the earlier coinbase output // this is not a valid tx as the coinbase output cannot be spent yet let coinbase_txn = build::transaction( + KernelFeatures::Plain { fee: 2 }, vec![ build::coinbase_input(amount, key_id1.clone()), build::output(amount - 2, key_id2.clone()), - build::with_fee(2), ], &keychain, &builder, diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 49a93fc1e..430bec8eb 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -463,42 +463,17 @@ impl TxKernel { /// Build an empty tx kernel with zero values. pub fn empty() -> TxKernel { + TxKernel::with_features(KernelFeatures::Plain { fee: 0 }) + } + + /// Build an empty tx kernel with the provided kernel features. + pub fn with_features(features: KernelFeatures) -> TxKernel { TxKernel { - features: KernelFeatures::Plain { fee: 0 }, + features, excess: Commitment::from_vec(vec![0; 33]), excess_sig: secp::Signature::from_raw_data(&[0; 64]).unwrap(), } } - - /// Builds a new tx kernel with the provided fee. - /// Will panic if we cannot safely do this on the existing kernel. - /// i.e. Do not try and set a fee on a coinbase kernel. - pub fn with_fee(self, fee: u64) -> TxKernel { - match self.features { - KernelFeatures::Plain { .. } => { - let features = KernelFeatures::Plain { fee }; - TxKernel { features, ..self } - } - KernelFeatures::HeightLocked { lock_height, .. } => { - let features = KernelFeatures::HeightLocked { fee, lock_height }; - TxKernel { features, ..self } - } - KernelFeatures::Coinbase => panic!("fee not supported on coinbase kernel"), - } - } - - /// Builds a new tx kernel with the provided lock_height. - /// Will panic if we cannot safely do this on the existing kernel. - /// i.e. Do not try and set a lock_height on a coinbase kernel. - pub fn with_lock_height(self, lock_height: u64) -> TxKernel { - match self.features { - KernelFeatures::Plain { fee } | KernelFeatures::HeightLocked { fee, .. } => { - let features = KernelFeatures::HeightLocked { fee, lock_height }; - TxKernel { features, ..self } - } - KernelFeatures::Coinbase => panic!("lock_height not supported on coinbase kernel"), - } - } } /// Enum of possible tx weight verification options - @@ -684,6 +659,13 @@ impl TransactionBody { self } + /// Builds a new TransactionBody replacing any existing kernels with the provided kernel. + pub fn replace_kernel(mut self, kernel: TxKernel) -> TransactionBody { + self.kernels.clear(); + self.kernels.push(kernel); + self + } + /// Total fee for a TransactionBody is the sum of fees of all fee carrying kernels. pub fn fee(&self) -> u64 { self.kernels @@ -1012,8 +994,8 @@ impl Transaction { } } - /// Builds a new transaction with the provided output added. Existing - /// outputs, if any, are kept intact. + /// Builds a new transaction with the provided kernel added. Existing + /// kernels, if any, are kept intact. /// Sort order is maintained. pub fn with_kernel(self, kernel: TxKernel) -> Transaction { Transaction { @@ -1022,6 +1004,14 @@ impl Transaction { } } + /// Builds a new transaction replacing any existing kernels with the provided kernel. + pub fn replace_kernel(self, kernel: TxKernel) -> Transaction { + Transaction { + body: self.body.replace_kernel(kernel), + ..self + } + } + /// Get inputs pub fn inputs(&self) -> &Vec { &self.body.inputs diff --git a/core/src/libtx/build.rs b/core/src/libtx/build.rs index f8087dc4e..89e43036d 100644 --- a/core/src/libtx/build.rs +++ b/core/src/libtx/build.rs @@ -22,10 +22,16 @@ //! _transaction_ function. //! //! Example: -//! build::transaction(vec![input_rand(75), output_rand(42), output_rand(32), -//! with_fee(1)]) +//! build::transaction( +//! KernelFeatures::Plain{ fee: 2 }, +//! vec![ +//! input_rand(75), +//! output_rand(42), +//! output_rand(32), +//! ] +//! ) -use crate::core::{Input, Output, OutputFeatures, Transaction, TxKernel}; +use crate::core::{Input, KernelFeatures, Output, OutputFeatures, Transaction, TxKernel}; use crate::keychain::{BlindSum, BlindingFactor, Identifier, Keychain}; use crate::libtx::proof::{self, ProofBuild}; use crate::libtx::{aggsig, Error}; @@ -44,11 +50,12 @@ where } /// Function type returned by the transaction combinators. Transforms a -/// (Transaction, BlindSum) pair into another, provided some context. +/// (Transaction, BlindSum) tuple into another, given the provided context. +/// Will return an Err if seomthing went wrong at any point during transaction building. pub type Append = dyn for<'a> Fn( &'a mut Context<'_, K, B>, - (Transaction, TxKernel, BlindSum), -) -> (Transaction, TxKernel, BlindSum); + Result<(Transaction, BlindSum), Error>, +) -> Result<(Transaction, BlindSum), Error>; /// Adds an input with the provided value and blinding key to the transaction /// being built. @@ -58,17 +65,21 @@ where B: ProofBuild, { Box::new( - move |build, (tx, kern, sum)| -> (Transaction, TxKernel, BlindSum) { - let commit = build - .keychain - .commit(value, &key_id, &SwitchCommitmentType::Regular) - .unwrap(); // TODO: proper support for different switch commitment schemes - let input = Input::new(features, commit); - ( - tx.with_input(input), - kern, - sum.sub_key_id(key_id.to_value_path(value)), - ) + move |build, acc| -> Result<(Transaction, BlindSum), Error> { + if let Ok((tx, sum)) = acc { + let commit = + build + .keychain + .commit(value, &key_id, &SwitchCommitmentType::Regular)?; + // TODO: proper support for different switch commitment schemes + let input = Input::new(features, commit); + Ok(( + tx.with_input(input), + sum.sub_key_id(key_id.to_value_path(value)), + )) + } else { + acc + } }, ) } @@ -105,11 +116,13 @@ where B: ProofBuild, { Box::new( - move |build, (tx, kern, sum)| -> (Transaction, TxKernel, BlindSum) { + move |build, acc| -> Result<(Transaction, BlindSum), Error> { + let (tx, sum) = acc?; + // TODO: proper support for different switch commitment schemes let switch = &SwitchCommitmentType::Regular; - let commit = build.keychain.commit(value, &key_id, switch).unwrap(); + let commit = build.keychain.commit(value, &key_id, switch)?; debug!("Building output: {}, {:?}", value, commit); @@ -121,44 +134,16 @@ where switch, commit, None, - ) - .unwrap(); + )?; - ( + Ok(( tx.with_output(Output { features: OutputFeatures::Plain, commit, proof: rproof, }), - kern, sum.add_key_id(key_id.to_value_path(value)), - ) - }, - ) -} - -/// Sets the fee on the transaction being built. -pub fn with_fee(fee: u64) -> Box> -where - K: Keychain, - B: ProofBuild, -{ - Box::new( - move |_build, (tx, kern, sum)| -> (Transaction, TxKernel, BlindSum) { - (tx, kern.with_fee(fee), sum) - }, - ) -} - -/// Sets the lock_height on the transaction being built. -pub fn with_lock_height(lock_height: u64) -> Box> -where - K: Keychain, - B: ProofBuild, -{ - Box::new( - move |_build, (tx, kern, sum)| -> (Transaction, TxKernel, BlindSum) { - (tx, kern.with_lock_height(lock_height), sum) + )) }, ) } @@ -172,53 +157,32 @@ where B: ProofBuild, { Box::new( - move |_build, (tx, kern, sum)| -> (Transaction, TxKernel, BlindSum) { - (tx, kern, sum.add_blinding_factor(excess.clone())) - }, - ) -} - -/// Sets a known tx "offset". Used in final step of tx construction. -pub fn with_offset(offset: BlindingFactor) -> Box> -where - K: Keychain, - B: ProofBuild, -{ - Box::new( - move |_build, (tx, kern, sum)| -> (Transaction, TxKernel, BlindSum) { - (tx.with_offset(offset.clone()), kern, sum) + move |_build, acc| -> Result<(Transaction, BlindSum), Error> { + acc.map(|(tx, sum)| (tx, sum.add_blinding_factor(excess.clone()))) }, ) } /// Sets an initial transaction to add to when building a new transaction. -/// We currently only support building a tx with a single kernel with -/// build::transaction() -pub fn initial_tx(mut tx: Transaction) -> Box> +pub fn initial_tx(tx: Transaction) -> Box> where K: Keychain, B: ProofBuild, { - assert_eq!(tx.kernels().len(), 1); - let kern = tx.kernels_mut().remove(0); Box::new( - move |_build, (_, _, sum)| -> (Transaction, TxKernel, BlindSum) { - (tx.clone(), kern.clone(), sum) + move |_build, acc| -> Result<(Transaction, BlindSum), Error> { + acc.map(|(_, sum)| (tx.clone(), sum)) }, ) } -/// Builds a new transaction by combining all the combinators provided in a -/// Vector. Transactions can either be built "from scratch" with a list of -/// inputs or outputs or from a pre-existing transaction that gets added to. +/// Takes an existing transaction and partially builds on it. /// /// Example: -/// let (tx1, sum) = build::transaction(vec![input_rand(4), output_rand(1), -/// with_fee(1)], keychain).unwrap(); -/// let (tx2, _) = build::transaction(vec![initial_tx(tx1), with_excess(sum), -/// output_rand(2)], keychain).unwrap(); +/// let (tx, sum) = build::transaction(tx, vec![input_rand(4), output_rand(1))], keychain)?; /// pub fn partial_transaction( + tx: Transaction, elems: Vec>>, keychain: &K, builder: &B, @@ -228,22 +192,16 @@ where B: ProofBuild, { let mut ctx = Context { keychain, builder }; - let (tx, kern, sum) = elems.iter().fold( - (Transaction::empty(), TxKernel::empty(), BlindSum::new()), - |acc, elem| elem(&mut ctx, acc), - ); + let (tx, sum) = elems + .iter() + .fold(Ok((tx, BlindSum::new())), |acc, elem| elem(&mut ctx, acc))?; let blind_sum = ctx.keychain.blind_sum(&sum)?; - - // we only support building a tx with a single kernel via build::transaction() - assert!(tx.kernels().is_empty()); - - let tx = tx.with_kernel(kern); - Ok((tx, blind_sum)) } /// Builds a complete transaction. pub fn transaction( + features: KernelFeatures, elems: Vec>>, keychain: &K, builder: &B, @@ -253,10 +211,11 @@ where B: ProofBuild, { let mut ctx = Context { keychain, builder }; - let (mut tx, mut kern, sum) = elems.iter().fold( - (Transaction::empty(), TxKernel::empty(), BlindSum::new()), - |acc, elem| elem(&mut ctx, acc), - ); + let (mut tx, sum) = elems + .iter() + .fold(Ok((Transaction::empty(), BlindSum::new())), |acc, elem| { + elem(&mut ctx, acc) + })?; let blind_sum = ctx.keychain.blind_sum(&sum)?; // Split the key so we can generate an offset for the tx. @@ -264,6 +223,8 @@ where let k1 = split.blind_1; let k2 = split.blind_2; + let mut kern = TxKernel::with_features(features); + // Construct the message to be signed. let msg = kern.msg_to_sign()?; @@ -271,17 +232,14 @@ where let skey = k1.secret_key(&keychain.secp())?; kern.excess = ctx.keychain.secp().commit(0, skey)?; let pubkey = &kern.excess.to_pubkey(&keychain.secp())?; - kern.excess_sig = - aggsig::sign_with_blinding(&keychain.secp(), &msg, &k1, Some(&pubkey)).unwrap(); + kern.excess_sig = aggsig::sign_with_blinding(&keychain.secp(), &msg, &k1, Some(&pubkey))?; // Store the kernel offset (k2) on the tx. // Commitments will sum correctly when accounting for the offset. tx.offset = k2.clone(); - // Set the kernel on the tx (assert this is now a single-kernel tx). - assert!(tx.kernels().is_empty()); - let tx = tx.with_kernel(kern); - assert_eq!(tx.kernels().len(), 1); + // Set the kernel on the tx. + let tx = tx.replace_kernel(kern); Ok(tx) } @@ -313,12 +271,8 @@ mod test { let vc = verifier_cache(); let tx = transaction( - vec![ - input(10, key_id1), - input(12, key_id2), - output(20, key_id3), - with_fee(2), - ], + KernelFeatures::Plain { fee: 2 }, + vec![input(10, key_id1), input(12, key_id2), output(20, key_id3)], &keychain, &builder, ) @@ -338,12 +292,8 @@ mod test { let vc = verifier_cache(); let tx = transaction( - vec![ - input(10, key_id1), - input(12, key_id2), - output(20, key_id3), - with_fee(2), - ], + KernelFeatures::Plain { fee: 2 }, + vec![input(10, key_id1), input(12, key_id2), output(20, key_id3)], &keychain, &builder, ) @@ -362,7 +312,8 @@ mod test { let vc = verifier_cache(); let tx = transaction( - vec![input(6, key_id1), output(2, key_id2), with_fee(4)], + KernelFeatures::Plain { fee: 4 }, + vec![input(6, key_id1), output(2, key_id2)], &keychain, &builder, ) diff --git a/core/src/libtx/error.rs b/core/src/libtx/error.rs index 957e8d49f..d6cbe6126 100644 --- a/core/src/libtx/error.rs +++ b/core/src/libtx/error.rs @@ -44,6 +44,9 @@ pub enum ErrorKind { /// Rangeproof error #[fail(display = "Rangeproof Error")] RangeProof(String), + /// Other error + #[fail(display = "Other Error")] + Other(String), } impl Fail for Error { diff --git a/core/tests/block.rs b/core/tests/block.rs index fd646e7bf..7101a8178 100644 --- a/core/tests/block.rs +++ b/core/tests/block.rs @@ -24,7 +24,7 @@ use crate::core::core::Committed; use crate::core::core::{ Block, BlockHeader, CompactBlock, HeaderVersion, KernelFeatures, OutputFeatures, }; -use crate::core::libtx::build::{self, input, output, with_fee}; +use crate::core::libtx::build::{self, input, output}; use crate::core::libtx::ProofBuilder; use crate::core::{global, ser}; use crate::keychain::{BlindingFactor, ExtKeychain, Keychain}; @@ -58,8 +58,9 @@ fn too_large_block() { parts.push(output(5, pks.pop().unwrap())); } - parts.append(&mut vec![input(500000, pks.pop().unwrap()), with_fee(2)]); - let tx = build::transaction(parts, &keychain, &builder).unwrap(); + parts.append(&mut vec![input(500000, pks.pop().unwrap())]); + let tx = + build::transaction(KernelFeatures::Plain { fee: 2 }, parts, &keychain, &builder).unwrap(); let prev = BlockHeader::default(); let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); @@ -92,7 +93,8 @@ fn block_with_cut_through() { let mut btx1 = tx2i1o(); let mut btx2 = build::transaction( - vec![input(7, key_id1), output(5, key_id2.clone()), with_fee(2)], + KernelFeatures::Plain { fee: 2 }, + vec![input(7, key_id1), output(5, key_id2.clone())], &keychain, &builder, ) @@ -477,12 +479,8 @@ fn same_amount_outputs_copy_range_proof() { let key_id3 = keychain::ExtKeychain::derive_key_id(1, 3, 0, 0, 0); let tx = build::transaction( - vec![ - input(7, key_id1), - output(3, key_id2), - output(3, key_id3), - with_fee(1), - ], + KernelFeatures::Plain { fee: 1 }, + vec![input(7, key_id1), output(3, key_id2), output(3, key_id3)], &keychain, &builder, ) @@ -527,23 +525,19 @@ fn wrong_amount_range_proof() { let key_id3 = keychain::ExtKeychain::derive_key_id(1, 3, 0, 0, 0); let tx1 = build::transaction( + KernelFeatures::Plain { fee: 1 }, vec![ input(7, key_id1.clone()), output(3, key_id2.clone()), output(3, key_id3.clone()), - with_fee(1), ], &keychain, &builder, ) .unwrap(); let tx2 = build::transaction( - vec![ - input(7, key_id1), - output(2, key_id2), - output(4, key_id3), - with_fee(1), - ], + KernelFeatures::Plain { fee: 1 }, + vec![input(7, key_id1), output(2, key_id2), output(4, key_id3)], &keychain, &builder, ) diff --git a/core/tests/common.rs b/core/tests/common.rs index b58536a19..d61466a9c 100644 --- a/core/tests/common.rs +++ b/core/tests/common.rs @@ -15,12 +15,9 @@ //! Common test functions use crate::keychain::{Identifier, Keychain}; -use grin_core::core::{ - block::{Block, BlockHeader}, - Transaction, -}; +use grin_core::core::{Block, BlockHeader, KernelFeatures, Transaction}; use grin_core::libtx::{ - build::{self, input, output, with_fee}, + build::{self, input, output}, proof::{ProofBuild, ProofBuilder}, reward, }; @@ -36,12 +33,8 @@ pub fn tx2i1o() -> Transaction { let key_id3 = keychain::ExtKeychain::derive_key_id(1, 3, 0, 0, 0); build::transaction( - vec![ - input(10, key_id1), - input(11, key_id2), - output(19, key_id3), - with_fee(2), - ], + KernelFeatures::Plain { fee: 2 }, + vec![input(10, key_id1), input(11, key_id2), output(19, key_id3)], &keychain, &builder, ) @@ -56,7 +49,8 @@ pub fn tx1i1o() -> Transaction { let key_id2 = keychain::ExtKeychain::derive_key_id(1, 2, 0, 0, 0); build::transaction( - vec![input(5, key_id1), output(3, key_id2), with_fee(2)], + KernelFeatures::Plain { fee: 2 }, + vec![input(5, key_id1), output(3, key_id2)], &keychain, &builder, ) @@ -74,12 +68,8 @@ pub fn tx1i2o() -> Transaction { let key_id3 = keychain::ExtKeychain::derive_key_id(1, 3, 0, 0, 0); build::transaction( - vec![ - input(6, key_id1), - output(3, key_id2), - output(1, key_id3), - with_fee(2), - ], + KernelFeatures::Plain { fee: 2 }, + vec![input(6, key_id1), output(3, key_id2), output(1, key_id3)], &keychain, &builder, ) @@ -124,7 +114,8 @@ where B: ProofBuild, { build::transaction( - vec![input(v, key_id1), output(3, key_id2), with_fee(2)], + KernelFeatures::Plain { fee: 2 }, + vec![input(v, key_id1), output(3, key_id2)], keychain, builder, ) diff --git a/core/tests/core.rs b/core/tests/core.rs index 618c51c8b..c99f3d6b4 100644 --- a/core/tests/core.rs +++ b/core/tests/core.rs @@ -20,10 +20,10 @@ use self::core::core::block::BlockHeader; use self::core::core::block::Error::KernelLockHeight; use self::core::core::hash::{Hashed, ZERO_HASH}; use self::core::core::verifier_cache::{LruVerifierCache, VerifierCache}; -use self::core::core::{aggregate, deaggregate, KernelFeatures, Output, Transaction, Weighting}; -use self::core::libtx::build::{ - self, initial_tx, input, output, with_excess, with_fee, with_lock_height, +use self::core::core::{ + aggregate, deaggregate, KernelFeatures, Output, Transaction, TxKernel, Weighting, }; +use self::core::libtx::build::{self, initial_tx, input, output, with_excess}; use self::core::libtx::ProofBuilder; use self::core::ser; use self::keychain::{BlindingFactor, ExtKeychain, Keychain}; @@ -99,6 +99,7 @@ fn test_zero_commit_fails() { // blinding should fail as signing with a zero r*G shouldn't work build::transaction( + KernelFeatures::Plain { fee: 0 }, vec![input(10, key_id1.clone()), output(10, key_id1.clone())], &keychain, &builder, @@ -120,12 +121,8 @@ fn build_tx_kernel() { // first build a valid tx with corresponding blinding factor let tx = build::transaction( - vec![ - input(10, key_id1), - output(5, key_id2), - output(3, key_id3), - with_fee(2), - ], + KernelFeatures::Plain { fee: 2 }, + vec![input(10, key_id1), output(5, key_id2), output(3, key_id3)], &keychain, &builder, ) @@ -373,12 +370,8 @@ fn hash_output() { let key_id3 = ExtKeychain::derive_key_id(1, 3, 0, 0, 0); let tx = build::transaction( - vec![ - input(75, key_id1), - output(42, key_id2), - output(32, key_id3), - with_fee(1), - ], + KernelFeatures::Plain { fee: 1 }, + vec![input(75, key_id1), output(42, key_id2), output(32, key_id3)], &keychain, &builder, ) @@ -439,12 +432,11 @@ fn tx_build_exchange() { // Alice builds her transaction, with change, which also produces the sum // of blinding factors before they're obscured. - let (tx, sum) = build::partial_transaction( - vec![in1, in2, output(1, key_id3), with_fee(2)], - &keychain, - &builder, - ) - .unwrap(); + let tx = Transaction::empty() + .with_kernel(TxKernel::with_features(KernelFeatures::Plain { fee: 2 })); + let (tx, sum) = + build::partial_transaction(tx, vec![in1, in2, output(1, key_id3)], &keychain, &builder) + .unwrap(); (tx, sum) }; @@ -453,6 +445,7 @@ fn tx_build_exchange() { // blinding factors. He adds his output, finalizes the transaction so it's // ready for broadcast. let tx_final = build::transaction( + KernelFeatures::Plain { fee: 2 }, vec![ initial_tx(tx_alice), with_excess(blind_sum), @@ -547,12 +540,11 @@ fn test_block_with_timelocked_tx() { // first check we can add a timelocked tx where lock height matches current // block height and that the resulting block is valid let tx1 = build::transaction( - vec![ - input(5, key_id1.clone()), - output(3, key_id2.clone()), - with_fee(2), - with_lock_height(1), - ], + KernelFeatures::HeightLocked { + fee: 2, + lock_height: 1, + }, + vec![input(5, key_id1.clone()), output(3, key_id2.clone())], &keychain, &builder, ) @@ -572,12 +564,11 @@ fn test_block_with_timelocked_tx() { // now try adding a timelocked tx where lock height is greater than current // block height let tx1 = build::transaction( - vec![ - input(5, key_id1.clone()), - output(3, key_id2.clone()), - with_fee(2), - with_lock_height(2), - ], + KernelFeatures::HeightLocked { + fee: 2, + lock_height: 2, + }, + vec![input(5, key_id1.clone()), output(3, key_id2.clone())], &keychain, &builder, ) diff --git a/pool/tests/common.rs b/pool/tests/common.rs index 82d2061bb..99b54fafb 100644 --- a/pool/tests/common.rs +++ b/pool/tests/common.rs @@ -18,7 +18,7 @@ use self::chain::store::ChainStore; use self::chain::types::Tip; use self::core::core::hash::{Hash, Hashed}; use self::core::core::verifier_cache::VerifierCache; -use self::core::core::{Block, BlockHeader, BlockSums, Committed, Transaction}; +use self::core::core::{Block, BlockHeader, BlockSums, Committed, KernelFeatures, Transaction}; use self::core::libtx; use self::keychain::{ExtKeychain, Keychain}; use self::pool::types::*; @@ -193,9 +193,13 @@ where tx_elements.push(libtx::build::output(output_value, key_id)); } - tx_elements.push(libtx::build::with_fee(fees as u64)); - - libtx::build::transaction(tx_elements, keychain, &libtx::ProofBuilder::new(keychain)).unwrap() + libtx::build::transaction( + KernelFeatures::Plain { fee: fees as u64 }, + tx_elements, + keychain, + &libtx::ProofBuilder::new(keychain), + ) + .unwrap() } pub fn test_transaction( @@ -223,9 +227,14 @@ where let key_id = ExtKeychain::derive_key_id(1, output_value as u32, 0, 0, 0); tx_elements.push(libtx::build::output(output_value, key_id)); } - tx_elements.push(libtx::build::with_fee(fees as u64)); - libtx::build::transaction(tx_elements, keychain, &libtx::ProofBuilder::new(keychain)).unwrap() + libtx::build::transaction( + KernelFeatures::Plain { fee: fees as u64 }, + tx_elements, + keychain, + &libtx::ProofBuilder::new(keychain), + ) + .unwrap() } pub fn test_source() -> TxSource {