diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index fce4026c06..1f6caa0b9d 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -53,4 +53,8 @@ tempfile.workspace = true [features] trezor = ["dep:trezor-client", "wallet-types/trezor"] enable-trezor-device-tests = [] +# Note: currently this is used in certain external tests (in particular, in the bridge), so we only +# allow it for regtest. TODO: it's better to have some regtest-specific options for the wallet, +# similar to what we have for the node. +use-deterministic-signatures-in-software-signer-for-regtest = [] default = ["trezor"] diff --git a/wallet/src/signer/software_signer/mod.rs b/wallet/src/signer/software_signer/mod.rs index 58299b03d4..f5036784d8 100644 --- a/wallet/src/signer/software_signer/mod.rs +++ b/wallet/src/signer/software_signer/mod.rs @@ -19,6 +19,7 @@ use itertools::Itertools; use common::{ chain::{ + config::ChainType, htlc::HtlcSecret, signature::{ inputsig::{ @@ -46,7 +47,7 @@ use common::{ use crypto::key::{ extended::{ExtendedPrivateKey, ExtendedPublicKey}, hdkd::{derivable::Derivable, u31::U31}, - PrivateKey, SigAuxDataProvider, + PredefinedSigAuxDataProvider, PrivateKey, SigAuxDataProvider, }; use randomness::make_true_rng; use wallet_storage::{ @@ -76,7 +77,22 @@ pub struct SoftwareSigner { impl SoftwareSigner { pub fn new(chain_config: Arc, account_index: U31) -> Self { - Self::new_with_sig_aux_data_provider(chain_config, account_index, Box::new(make_true_rng())) + let use_deterministic_signer = *chain_config.chain_type() == ChainType::Regtest + && cfg!(feature = "use-deterministic-signatures-in-software-signer-for-regtest"); + + if use_deterministic_signer { + Self::new_with_sig_aux_data_provider( + chain_config, + account_index, + Box::new(PredefinedSigAuxDataProvider), + ) + } else { + Self::new_with_sig_aux_data_provider( + chain_config, + account_index, + Box::new(make_true_rng()), + ) + } } pub fn new_with_sig_aux_data_provider( diff --git a/wallet/types/src/partially_signed_transaction.rs b/wallet/types/src/partially_signed_transaction.rs index 091bec1612..063d9cf11c 100644 --- a/wallet/types/src/partially_signed_transaction.rs +++ b/wallet/types/src/partially_signed_transaction.rs @@ -32,8 +32,9 @@ use common::{ Signable, Transactable, }, tokens::TokenId, - ChainConfig, Destination, OrderId, PoolId, SighashInputCommitmentVersion, - SignedTransaction, Transaction, TransactionCreationError, TxInput, TxOutput, + AccountCommand, ChainConfig, Destination, OrderAccountCommand, OrderId, PoolId, + SighashInputCommitmentVersion, SignedTransaction, Transaction, TransactionCreationError, + TxInput, TxOutput, }, primitives::{Amount, BlockHeight}, }; @@ -160,6 +161,14 @@ impl TxAdditionalInfo { self.order_info.get(order_id) } + pub fn token_info_iter(&self) -> impl Iterator { + self.token_info.iter() + } + + pub fn pool_info_iter(&self) -> impl Iterator { + self.pool_info.iter() + } + pub fn order_info_iter(&self) -> impl Iterator { self.order_info.iter() } @@ -211,31 +220,51 @@ pub struct PartiallySignedTransaction { } impl PartiallySignedTransaction { - pub fn new( + pub fn new_unchecked( tx: Transaction, witnesses: Vec>, input_utxos: Vec>, destinations: Vec>, htlc_secrets: Option>>, additional_info: TxAdditionalInfo, - ) -> Result { + ) -> Self { let htlc_secrets = htlc_secrets.unwrap_or_else(|| vec![None; tx.inputs().len()]); - let this = Self { + Self { tx, witnesses, input_utxos, destinations, htlc_secrets, additional_info, - }; + } + } - this.ensure_consistency()?; + pub fn new( + tx: Transaction, + witnesses: Vec>, + input_utxos: Vec>, + destinations: Vec>, + htlc_secrets: Option>>, + additional_info: TxAdditionalInfo, + ) -> Result { + let this = Self::new_unchecked( + tx, + witnesses, + input_utxos, + destinations, + htlc_secrets, + additional_info, + ); + this.ensure_consistency(Self::need_heavy_consistency_checks())?; Ok(this) } - pub fn ensure_consistency(&self) -> Result<(), PartiallySignedTransactionError> { + pub fn ensure_consistency( + &self, + with_heavy_checks: bool, + ) -> Result<(), PartiallySignedTransactionError> { ensure!( self.tx.inputs().len() == self.witnesses.len(), PartiallySignedTransactionError::InvalidWitnessCount @@ -256,18 +285,18 @@ impl PartiallySignedTransaction { PartiallySignedTransactionError::InvalidHtlcSecretsCount ); - #[cfg(debug_assertions)] - { + if with_heavy_checks { self.ensure_additional_info_completeness()?; } Ok(()) } - #[cfg(debug_assertions)] - fn ensure_additional_info_completeness(&self) -> Result<(), PartiallySignedTransactionError> { - use common::chain::{AccountCommand, OrderAccountCommand}; + fn need_heavy_consistency_checks() -> bool { + cfg!(debug_assertions) + } + fn ensure_additional_info_completeness(&self) -> Result<(), PartiallySignedTransactionError> { let ensure_order_info_present = |order_id: &OrderId| -> Result<_, PartiallySignedTransactionError> { ensure!( @@ -387,7 +416,7 @@ impl PartiallySignedTransaction { witnesses: Vec>, ) -> Result { self.witnesses = witnesses; - self.ensure_consistency()?; + self.ensure_consistency(Self::need_heavy_consistency_checks())?; Ok(self) }