From 109c591fc6f1338406238fd624a1136f8c91b3ee Mon Sep 17 00:00:00 2001 From: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Date: Fri, 27 Mar 2020 13:28:44 +0800 Subject: [PATCH] Problem: revised fees not implemented (fixes #1302) Solution: deposit, transfer, withdraw enforce min fee; (unbond tx already only had min fee) adjusted tests + temporary fixes for client, as its fee estimation has problems (e.g. it hardcoded unlocking condititions to "two pubkeys" so it estimated higher fees + mocks in unit tests are broken) --- chain-abci/src/enclave_bridge/real/server.rs | 4 +- .../src/enclave_bridge/real/test/seal.rs | 3 +- chain-abci/tests/abci_app.rs | 17 +- chain-abci/tests/tx_validation.rs | 4 +- chain-tx-enclave/tx-query/enclave/src/lib.rs | 22 +- chain-tx-validation/src/lib.rs | 17 +- client-core/src/signer/dummy_signer.rs | 21 +- .../default_wallet_transaction_builder.rs | 53 ++++- .../raw_transfer_transaction_builder.rs | 219 ++++++++++++------ .../network_ops/default_network_ops_client.rs | 3 +- cro-clib/src/transaction_build.rs | 2 + cro-clib/src/transaction_deposit.rs | 1 + enclave-protocol/src/lib.rs | 2 + 13 files changed, 250 insertions(+), 118 deletions(-) diff --git a/chain-abci/src/enclave_bridge/real/server.rs b/chain-abci/src/enclave_bridge/real/server.rs index 384f6c59c..bc1506908 100644 --- a/chain-abci/src/enclave_bridge/real/server.rs +++ b/chain-abci/src/enclave_bridge/real/server.rs @@ -80,8 +80,8 @@ impl TxValidationServer { let min_fee = last_state .top_level .network_params - .get_min_const_fee() - .expect("invalid fee policy"); + .calculate_fee(req.tx_size as usize) + .expect("valid fee"); let info = ChainInfo { min_fee_computed: min_fee, chain_hex_id: self.network_id, diff --git a/chain-abci/src/enclave_bridge/real/test/seal.rs b/chain-abci/src/enclave_bridge/real/test/seal.rs index b97fb5974..c9e5087bf 100644 --- a/chain-abci/src/enclave_bridge/real/test/seal.rs +++ b/chain-abci/src/enclave_bridge/real/test/seal.rs @@ -186,12 +186,11 @@ pub fn test_sealing() { } }; - let halfcoin = Coin::from(5000_0000u32); let utxo1 = TxoPointer::new(*txid, 0); let mut tx1 = Tx::new(); tx1.attributes = TxAttributes::new(TEST_NETWORK_ID); tx1.add_input(utxo1.clone()); - tx1.add_output(TxOut::new(eaddr.clone(), halfcoin)); + tx1.add_output(TxOut::new(eaddr.clone(), Coin::one())); let txid1 = tx1.id(); let witness1 = vec![TxInWitness::TreeSig( schnorr_sign(&secp, &Message::from_slice(&txid1).unwrap(), &secret_key), diff --git a/chain-abci/tests/abci_app.rs b/chain-abci/tests/abci_app.rs index 2bb8ffc4d..851291933 100644 --- a/chain-abci/tests/abci_app.rs +++ b/chain-abci/tests/abci_app.rs @@ -432,12 +432,17 @@ fn prepare_app_valid_tx() -> (ChainNodeApp, TxAux, WithdrawUnbondedT let public_key = PublicKey::from_secret_key(&secp, &secret_key); let addr = RedeemAddress::from(&public_key); let app = init_chain_for(addr); - let tx = WithdrawUnbondedTx::new( 0, vec![ TxOut::new_with_timelock(ExtendedAddr::OrTree([0; 32]), Coin::one(), 0), TxOut::new_with_timelock(ExtendedAddr::OrTree([1; 32]), Coin::unit(), 0), + // leftover -- in previous tests, it was all paid as a fee + TxOut::new_with_timelock( + ExtendedAddr::OrTree([2; 32]), + Coin::new(9999999999899999668).unwrap(), + 0, + ), ], TxAttributes::new_with_access(0, vec![TxAccessPolicy::new(public_key, TxAccess::AllData)]), ); @@ -572,9 +577,9 @@ fn deliver_tx_should_add_valid_tx() { assert_eq!(1, app.delivered_txs.len()); assert_eq!(1, cresp.events.len()); assert_eq!(3, cresp.events[0].attributes.len()); - // the unit test transaction just has two outputs: 1 CRO + 1 carson / base unit, the rest goes to a fee + // the unit test transaction just three outputs: 1 CRO + 1 carson / base unit + the rest assert_eq!( - &b"99999999998.99999998".to_vec(), + &b"0.00000330".to_vec(), &cresp.events[0].attributes[0].value ); assert_eq!( @@ -814,6 +819,7 @@ fn all_valid_tx_types_should_commit() { TxOut::new_with_timelock(eaddr.clone(), Coin::one(), 0), TxOut::new_with_timelock(eaddr.clone(), (Coin::one() + Coin::one()).unwrap(), 0), TxOut::new_with_timelock(eaddr.clone(), Coin::one(), 0), + TxOut::new_with_timelock(eaddr.clone(), Coin::new(9999999999599999619).unwrap(), 0), // rest ], TxAttributes::new_with_access(0, vec![TxAccessPolicy::new(public_key, TxAccess::AllData)]), ); @@ -843,11 +849,10 @@ fn all_valid_tx_types_should_commit() { let spend_utxos = get_tx_meta(&txid, &app); assert!(!spend_utxos.any()); } - let halfcoin = Coin::from(5000_0000u32); let utxo1 = TxoPointer::new(*txid, 0); let mut tx1 = Tx::new(); tx1.add_input(utxo1); - tx1.add_output(TxOut::new(eaddr, halfcoin)); + tx1.add_output(TxOut::new(eaddr, Coin::from(99999685u32))); let txid1 = tx1.id(); let witness1 = vec![TxInWitness::TreeSig( schnorr_sign(&secp, &Message::from_slice(&txid1).unwrap(), &secret_key), @@ -1018,7 +1023,7 @@ fn query_should_return_proof_for_committed_tx() { app.begin_block(&env.req_begin_block(1, 0)); - let tx_aux = env.unbond_tx((Coin::max() / 10).unwrap(), 0, 0); + let tx_aux = env.unbond_tx(Coin::new(5000000000000000000).unwrap(), 0, 0); let rsp_tx = app.deliver_tx(&RequestDeliverTx { tx: tx_aux.encode(), ..Default::default() diff --git a/chain-abci/tests/tx_validation.rs b/chain-abci/tests/tx_validation.rs index 0c72ea10b..1712c505c 100644 --- a/chain-abci/tests/tx_validation.rs +++ b/chain-abci/tests/tx_validation.rs @@ -229,7 +229,7 @@ fn prepare_app_valid_transfer_tx( tx.add_output(TxOut::new(addr, Coin::new(9).unwrap())); let sk2 = SecretKey::from_slice(&[0x11; 32]).expect("32 bytes, within curve order"); let addr2 = get_address(&secp, &sk2).0; - tx.add_output(TxOut::new(addr2, Coin::new(1).unwrap())); + tx.add_output(TxOut::new(addr2, Coin::new(99999634).unwrap())); let witness: Vec = vec![get_tx_witness(secp, &tx.id(), &secret_key, &merkle_tree)]; let plain_txaux = PlainTxAux::new(tx.clone(), witness.clone().into()); @@ -428,7 +428,7 @@ fn prepare_app_valid_withdraw_tx( let outputs = vec![ TxOut::new_with_timelock(addr1, Coin::new(9).unwrap(), 0), - TxOut::new_with_timelock(addr2, Coin::new(1).unwrap(), 0), + TxOut::new_with_timelock(addr2, Coin::new(99999745).unwrap(), 0), ]; let tx = WithdrawUnbondedTx::new(1, outputs, TxAttributes::new(DEFAULT_CHAIN_ID)); diff --git a/chain-tx-enclave/tx-query/enclave/src/lib.rs b/chain-tx-enclave/tx-query/enclave/src/lib.rs index a298dc36b..aec0fb439 100644 --- a/chain-tx-enclave/tx-query/enclave/src/lib.rs +++ b/chain-tx-enclave/tx-query/enclave/src/lib.rs @@ -159,38 +159,44 @@ fn get_sealed_request(req: &EncryptionRequest, txid: &TxId) -> Option> { Some(sealed_log) } -fn construct_request(req: &EncryptionRequest) -> Option { - let (txid, sealed, tx_inputs) = match req { +fn construct_request(req: &EncryptionRequest, req_len: usize) -> Option { + let (txid, sealed, tx_inputs, tx_size) = match req { + // TODO: are the size estimates ok? EncryptionRequest::TransferTx(tx, _) => { let txid = tx.id(); let sealed = get_sealed_request(&req, &txid); let tx_inputs = Some(tx.inputs.clone()); - (txid, sealed, tx_inputs) + (txid, sealed, tx_inputs, req_len + 34 * tx.inputs.len() + 74) } EncryptionRequest::DepositStake(tx, _) => { let txid = tx.id(); let sealed = get_sealed_request(&req, &txid); let tx_inputs = Some(tx.inputs.clone()); - (txid, sealed, tx_inputs) + (txid, sealed, tx_inputs, req_len + 34 * tx.inputs.len() + 74) } - EncryptionRequest::WithdrawStake(tx, _, _) => { + EncryptionRequest::WithdrawStake(tx, state, _) => { let txid = tx.id(); let sealed = get_sealed_request(&req, &txid); - (txid, sealed, None) + let state_len = state.encode().len(); + // FIXME: no need to send state in request + (txid, sealed, None, req_len - state_len + 73) } }; sealed.map(|sealed_enc_request| QueryEncryptRequest { txid, sealed_enc_request, tx_inputs, + // TODO: checks, but this should fit, as all things are bounded more like u16::max + tx_size: tx_size as u32, }) } fn handle_encryption_request( tls: &mut rustls::Stream, req: EncryptionRequest, + req_len: usize, ) -> sgx_status_t { - let request = construct_request(&req); + let request = construct_request(&req, req_len); match request { None => { let _ = tls.sock.shutdown(Shutdown::Both); @@ -281,7 +287,7 @@ pub extern "C" fn run_server(socket_fd: c_int, timeout: c_int) -> sgx_status_t { let mut plain = vec![0; ENCRYPTION_REQUEST_SIZE]; match tls.read(&mut plain) { Ok(l) => match TxQueryInitRequest::decode(&mut &plain.as_slice()[0..l]) { - Ok(TxQueryInitRequest::Encrypt(req)) => handle_encryption_request(&mut tls, *req), + Ok(TxQueryInitRequest::Encrypt(req)) => handle_encryption_request(&mut tls, *req, l), Ok(TxQueryInitRequest::DecryptChallenge) => handle_decryption_request(&mut tls, plain), _ => { let _ = conn.shutdown(Shutdown::Both); diff --git a/chain-tx-validation/src/lib.rs b/chain-tx-validation/src/lib.rs index de9a74221..228c5260b 100644 --- a/chain-tx-validation/src/lib.rs +++ b/chain-tx-validation/src/lib.rs @@ -258,17 +258,16 @@ fn check_input_output_sums( outcoins: Coin, extra_info: &ChainInfo, ) -> Result { - // check sum(input amounts) >= sum(output amounts) + minimum fee + // check sum(input amounts) == sum(output amounts) + minimum fee let min_fee: Coin = extra_info.min_fee_computed.to_coin(); let total_outsum = outcoins + min_fee; if let Err(_coin_err) = total_outsum { return Err(Error::InvalidSum); // FIXME: Err(Error::InvalidSum(coin_err)); } - if incoins < total_outsum.unwrap() { + if incoins != total_outsum.unwrap() { return Err(Error::InputOutputDoNotMatch); } - let fee_paid = (incoins - outcoins).unwrap(); - Ok(Fee::new(fee_paid)) + Ok(Fee::new(min_fee)) } /// checks TransferTx -- TODO: this will be moved to an enclave @@ -383,7 +382,15 @@ pub fn verify_unbonding( if maintx.value == Coin::zero() { return Err(Error::ZeroCoin); } - check_input_output_sums(account.bonded, maintx.value, extra_info)?; + // check that it's enough for fee + amount to be unbonded + let min_fee: Coin = extra_info.min_fee_computed.to_coin(); + let total_outsum = maintx.value + min_fee; + if let Err(_coin_err) = total_outsum { + return Err(Error::InvalidSum); + } + if account.bonded < total_outsum.unwrap() { + return Err(Error::InputOutputDoNotMatch); + } account.unbond( maintx.value, extra_info.min_fee_computed.to_coin(), diff --git a/client-core/src/signer/dummy_signer.rs b/client-core/src/signer/dummy_signer.rs index e9ef5f221..d0e9e0a9d 100644 --- a/client-core/src/signer/dummy_signer.rs +++ b/client-core/src/signer/dummy_signer.rs @@ -1,3 +1,4 @@ +use crate::transaction_builder::WitnessedUTxO; use chain_core::common::MerkleTree; use chain_core::common::H256; use chain_core::init::address::RedeemAddress; @@ -50,14 +51,13 @@ impl DummySigner { } /// Schnorr sign consecutive imaginary inputs of provided length - pub fn schnorr_sign_inputs_len( - &self, - total_pubkeys_len: usize, - inputs_len: usize, - ) -> Result { - let dummy_witness = self.sign_tx(total_pubkeys_len)?; - Ok(std::iter::repeat(dummy_witness) - .take(inputs_len) + pub fn schnorr_sign_inputs_len(&self, inputs: &[WitnessedUTxO]) -> Result { + Ok(inputs + .iter() + .map(|x| { + self.sign_tx(x.threshold as usize) + .expect("would that ever fail? why this dummy has results?") + }) .collect::>() .into()) } @@ -81,9 +81,8 @@ impl DummySigner { } /// Mock the txaux for deposit transactions - pub fn mock_txaux_for_deposit(&self, input_len: usize) -> Result { - let total_pubkeys_len = 1; - let witness = self.schnorr_sign_inputs_len(total_pubkeys_len, input_len)?; + pub fn mock_txaux_for_deposit(&self, inputs: &[WitnessedUTxO]) -> Result { + let witness = self.schnorr_sign_inputs_len(inputs)?; let plain_payload = PlainTxAux::DepositStakeTx(witness); let padded_payload = self.pad_payload(plain_payload); let deposit_bond_tx = DepositBondTx { diff --git a/client-core/src/transaction_builder/default_wallet_transaction_builder.rs b/client-core/src/transaction_builder/default_wallet_transaction_builder.rs index 4a7b4e2e5..d544a771c 100644 --- a/client-core/src/transaction_builder/default_wallet_transaction_builder.rs +++ b/client-core/src/transaction_builder/default_wallet_transaction_builder.rs @@ -42,13 +42,15 @@ where transaction_obfuscation: O, } -impl WalletTransactionBuilder for DefaultWalletTransactionBuilder +impl DefaultWalletTransactionBuilder where S: Storage, F: FeeAlgorithm + Clone, O: TransactionObfuscation, { - fn build_transfer_tx( + /// FIXME: temporary for broken fee estimation + #[allow(clippy::too_many_arguments)] + fn build_transfer_tx_ex( &self, name: &str, enckey: &SecKey, @@ -56,12 +58,15 @@ where outputs: Vec, return_address: ExtendedAddr, attributes: TxAttributes, + // FIXME: this should be per unspent_transactions + threshold: u16, ) -> Result<(TxAux, Vec, Coin)> { let mut raw_builder = self.select_and_build( &unspent_transactions, outputs, return_address.clone(), attributes, + threshold, )?; let selected_inputs: Vec = raw_builder @@ -84,6 +89,33 @@ where Ok((tx_aux, selected_inputs, return_amount)) } +} + +impl WalletTransactionBuilder for DefaultWalletTransactionBuilder +where + S: Storage, + F: FeeAlgorithm + Clone, + O: TransactionObfuscation, +{ + fn build_transfer_tx( + &self, + name: &str, + enckey: &SecKey, + unspent_transactions: UnspentTransactions, + outputs: Vec, + return_address: ExtendedAddr, + attributes: TxAttributes, + ) -> Result<(TxAux, Vec, Coin)> { + self.build_transfer_tx_ex( + name, + enckey, + unspent_transactions, + outputs, + return_address, + attributes, + 1, + ) + } #[inline] fn obfuscate(&self, signed_transaction: SignedTransaction) -> Result { @@ -130,6 +162,8 @@ where outputs: Vec, return_address: ExtendedAddr, attributes: TxAttributes, + // FIXME: this should be per UnspentTransactions + threshold: u16, ) -> Result> { let output_value = sum_coins(outputs.iter().map(|output| output.value)).chain(|| { ( @@ -152,6 +186,7 @@ where return_address.clone(), change_amount, attributes.clone(), + threshold, ); let new_fees = raw_tx_builder.estimate_fee()?; @@ -172,11 +207,13 @@ where return_address: ExtendedAddr, change_amount: Coin, attributes: TxAttributes, + // FIXME: this should be per SelectedUnspentTransactions + threshold: u16, ) -> RawTransferTransactionBuilder { let mut raw_tx_builder = RawTransferTransactionBuilder::new(attributes, self.fee_algorithm.clone()); for input in selected_unspent_transactions.iter() { - raw_tx_builder.add_input(input.clone()); + raw_tx_builder.add_input(input.clone(), threshold); } for output in outputs.iter() { raw_tx_builder.add_output(output.clone()); @@ -313,13 +350,14 @@ mod default_wallet_transaction_builder_tests { )]; let attributes = TxAttributes::new(171); let (tx_aux, _selected_inputs, _return_amount) = transaction_builder - .build_transfer_tx( + .build_transfer_tx_ex( name, &enckey, unspent_transactions.clone(), outputs, return_address, attributes, + 2, ) .unwrap(); @@ -351,7 +389,12 @@ mod default_wallet_transaction_builder_tests { } })) .unwrap(); - assert!((output_value + fee).unwrap() <= input_value); + // FIXME: all these unit tests don't account for 16-byte tag in encryption + // in those mock encrypt stuff, while the estimation does :/ + assert!( + (output_value + fee).unwrap() <= + (input_value - Coin::from(16u32)).unwrap() + ); for (i, input) in transaction.inputs.iter().enumerate() { let address = if input.id == [3; 32] { diff --git a/client-core/src/transaction_builder/raw_transfer_transaction_builder.rs b/client-core/src/transaction_builder/raw_transfer_transaction_builder.rs index f6ef5218b..b5afe9712 100644 --- a/client-core/src/transaction_builder/raw_transfer_transaction_builder.rs +++ b/client-core/src/transaction_builder/raw_transfer_transaction_builder.rs @@ -34,6 +34,8 @@ pub struct WitnessedUTxO { /// signature and merkleproof of rawpubkey /// rawpubkey: combinded key of publickeys for multisig pub witness: Option, + /// max options -- for determining the merkle proof size estimate in the witness, e.g. 2-of-3 threshold has 3 leaves (each is combined 2-of-2 pubkey) + pub threshold: u16, } impl WitnessedUTxO { @@ -41,6 +43,16 @@ impl WitnessedUTxO { pub fn has_witness(&self) -> bool { self.witness.is_some() } + + /// creates a dummy value + pub fn dummy() -> Self { + WitnessedUTxO { + prev_txo_pointer: TxoPointer::new(Default::default(), Default::default()), + prev_tx_out: TxOut::new(ExtendedAddr::OrTree([0u8; 32]), Default::default()), + witness: None, + threshold: 1, + } + } } /// When withdraw some coin from an offline wallet(W_A),the struct is build from an @@ -161,10 +173,11 @@ where /// # Warning /// When a new input is appended, any previous witness will be cleared /// because transaction id will be changed - pub fn add_input(&mut self, input: (TxoPointer, TxOut)) { + pub fn add_input(&mut self, input: (TxoPointer, TxOut), threshold: u16) { self.raw_transaction.inputs.push(WitnessedUTxO { prev_txo_pointer: input.0, prev_tx_out: input.1, + threshold, witness: None, }); @@ -335,8 +348,7 @@ where /// Estimate transaction fee with dummy signatures pub fn estimate_fee(&self) -> Result { let dummy_signer = DummySigner(); - let total_pubkeys_len = 2; - let witness = dummy_signer.schnorr_sign_inputs_len(total_pubkeys_len, self.inputs_len())?; + let witness = dummy_signer.schnorr_sign_inputs_len(&self.raw_transaction.inputs)?; let tx_aux = dummy_signer.mock_txaux_for_tx(self.to_tx(), witness); let estimated_fee = self .fee_algorithm @@ -439,6 +451,7 @@ where fn verify_fee(&self) -> Result<()> { let fee_expected = self.estimate_fee()?; let fee_in_tx = self.fee()?; + // FIXME: this should be !=, but unit tests don't have proper mocks if fee_in_tx < fee_expected { let fee_gap = (fee_expected - fee_in_tx).unwrap(); return Err(Error::new( @@ -593,10 +606,13 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(100).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(100).unwrap()), + ), + 1, + ); let tx = builder.to_transaction(); builder @@ -619,10 +635,13 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(100).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(100).unwrap()), + ), + 1, + ); builder.add_output(TxOut::new( ExtendedAddr::OrTree(random()), @@ -656,10 +675,13 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(100).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(100).unwrap()), + ), + 1, + ); builder.add_output(TxOut::new( ExtendedAddr::OrTree(random()), @@ -707,7 +729,7 @@ mod raw_transfer_transaction_builder_tests { TxoPointer::new(random(), 0), TxOut::new(ExtendedAddr::OrTree(random()), Coin::new(100).unwrap()), ); - builder.add_input(input.clone()); + builder.add_input(input.clone(), 1); assert_eq!(builder.inputs_len(), 1); assert_eq!(builder.input_at_index(0).unwrap().prev_txo_pointer, input.0); @@ -729,10 +751,13 @@ mod raw_transfer_transaction_builder_tests { assert!(builder.input_at_index(input_index).unwrap().has_witness()); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(100).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(100).unwrap()), + ), + 1, + ); assert!(!builder.input_at_index(input_index).unwrap().has_witness()); } @@ -771,10 +796,13 @@ mod raw_transfer_transaction_builder_tests { assert!(builder.input_at_index(input_index).unwrap().has_witness()); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(100).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(100).unwrap()), + ), + 1, + ); assert!(!builder.input_at_index(input_index).unwrap().has_witness()); } @@ -810,18 +838,27 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(ExtendedAddr::OrTree(random()), Coin::new(200).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(200).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(ExtendedAddr::OrTree(random()), Coin::new(200).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(200).unwrap()), + ), + 1, + ); builder.add_output(TxOut::new( ExtendedAddr::OrTree(random()), @@ -861,18 +898,27 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(ExtendedAddr::OrTree(random()), Coin::new(200).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(200).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(ExtendedAddr::OrTree(random()), Coin::new(200).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(200).unwrap()), + ), + 1, + ); builder.add_output(TxOut::new( ExtendedAddr::OrTree(random()), @@ -896,18 +942,27 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(ExtendedAddr::OrTree(random()), Coin::new(200).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(200).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(ExtendedAddr::OrTree(random()), Coin::new(200).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(200).unwrap()), + ), + 1, + ); builder.add_output(TxOut::new( ExtendedAddr::OrTree(random()), @@ -1027,14 +1082,20 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(200).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr.clone(), Coin::new(100).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(200).unwrap()), + ), + 1, + ); builder.add_output(TxOut::new( ExtendedAddr::OrTree(random()), @@ -1142,14 +1203,20 @@ mod raw_transfer_transaction_builder_tests { let fee_algorithm = create_testing_fee_algorithm(); let mut builder = RawTransferTransactionBuilder::new(attributes, fee_algorithm); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr.clone(), Coin::new(501).unwrap()), - )); - builder.add_input(( - TxoPointer::new(random(), 0), - TxOut::new(transfer_addr, Coin::new(500).unwrap()), - )); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr.clone(), Coin::new(501).unwrap()), + ), + 1, + ); + builder.add_input( + ( + TxoPointer::new(random(), 0), + TxOut::new(transfer_addr, Coin::new(500).unwrap()), + ), + 1, + ); builder.add_output(TxOut::new( ExtendedAddr::OrTree(random()), diff --git a/client-network/src/network_ops/default_network_ops_client.rs b/client-network/src/network_ops/default_network_ops_client.rs index 5cb7bc6e1..f365b7b58 100644 --- a/client-network/src/network_ops/default_network_ops_client.rs +++ b/client-network/src/network_ops/default_network_ops_client.rs @@ -21,6 +21,7 @@ use client_common::{ Error, ErrorKind, Result, ResultExt, SecKey, SignedTransaction, Storage, Transaction, }; use client_core::signer::{DummySigner, Signer, WalletSignerManager}; +use client_core::transaction_builder::WitnessedUTxO; use client_core::types::TransactionPending; use client_core::{TransactionObfuscation, UnspentTransactions, WalletClient}; use tendermint::Time; @@ -141,7 +142,7 @@ where fn calculate_deposit_fee(&self) -> Result { let dummy_signer = DummySigner(); let tx_aux = dummy_signer - .mock_txaux_for_deposit(1) + .mock_txaux_for_deposit(&[WitnessedUTxO::dummy()]) .chain(|| (ErrorKind::ValidationError, "Calculated fee failed"))?; let fee = self .fee_algorithm diff --git a/cro-clib/src/transaction_build.rs b/cro-clib/src/transaction_build.rs index 4e97f0d14..1898f2e77 100644 --- a/cro-clib/src/transaction_build.rs +++ b/cro-clib/src/transaction_build.rs @@ -69,6 +69,7 @@ fn add_txin(tx: &mut CroTx, txid_hex: &str, txindex: u16, addr: &str, coin: u64) prev_txo_pointer: txin_pointer, prev_tx_out: txin, witness: None, + threshold: 1, }; tx.txin.push(utxo); assert!(tx.tx.inputs.len() == tx.txin.len()); @@ -122,6 +123,7 @@ pub unsafe extern "C" fn cro_tx_add_txin_raw( prev_txo_pointer: txin_pointer, prev_tx_out: txin, witness: None, + threshold: 1, }; tx.txin.push(utxo); assert!(tx.tx.inputs.len() == tx.txin.len()); diff --git a/cro-clib/src/transaction_deposit.rs b/cro-clib/src/transaction_deposit.rs index f7022e439..99c5db529 100644 --- a/cro-clib/src/transaction_deposit.rs +++ b/cro-clib/src/transaction_deposit.rs @@ -123,6 +123,7 @@ fn add_txin_deposit( prev_txo_pointer: txin_pointer, prev_tx_out: txin, witness: None, + threshold: 1, }; tx.txin.push(utxo); assert!(tx.tx.inputs.len() == tx.txin.len()); diff --git a/enclave-protocol/src/lib.rs b/enclave-protocol/src/lib.rs index 2a4f25b27..12f46cecc 100644 --- a/enclave-protocol/src/lib.rs +++ b/enclave-protocol/src/lib.rs @@ -165,6 +165,8 @@ pub struct QueryEncryptRequest { pub txid: TxId, /// EncryptionRequest sealed by TQE to "mrsigner" pub sealed_enc_request: SealedLog, + /// plain tx size + pub tx_size: u32, /// transaction inputs (if any) pub tx_inputs: Option>, }