]> Untitled Git - bdk/commitdiff
General cleanup for the docs
authorAlekos Filini <alekos.filini@gmail.com>
Mon, 31 Aug 2020 08:49:44 +0000 (10:49 +0200)
committerAlekos Filini <alekos.filini@gmail.com>
Mon, 31 Aug 2020 13:04:27 +0000 (15:04 +0200)
23 files changed:
Cargo.toml
examples/address_validator.rs
src/blockchain/compact_filters/mod.rs
src/blockchain/compact_filters/peer.rs
src/blockchain/electrum.rs
src/blockchain/esplora.rs
src/blockchain/mod.rs
src/blockchain/utils.rs
src/cli.rs
src/database/mod.rs
src/descriptor/error.rs
src/descriptor/policy.rs
src/error.rs
src/lib.rs
src/types.rs
src/wallet/address_validator.rs
src/wallet/coin_selection.rs
src/wallet/mod.rs
src/wallet/signer.rs
src/wallet/time.rs
src/wallet/tx_builder.rs
src/wallet/utils.rs
testutils-macros/src/lib.rs

index ec9624b2a40bfc8c07943ee8e3f958c5d68cc070..599e8072a603cc2abf1d492aa745274aa608552f 100644 (file)
@@ -83,3 +83,10 @@ required-features = ["cli-utils"]
 
 [workspace]
 members = ["macros", "testutils", "testutils-macros"]
+
+# Generate docs with nightly to add the "features required" badge
+# https://stackoverflow.com/questions/61417452/how-to-get-a-feature-requirement-tag-in-the-documentation-generated-by-cargo-do
+[package.metadata.docs.rs]
+features = ["compiler", "electrum", "esplora", "compact_filters", "key-value-db"]
+# defines the configuration attribute `docsrs`
+rustdoc-args = ["--cfg", "docsrs"]
index 1cf766c88ca53c4f1b1fcb41dac1bf1b3455bce7..639bbdfdd30565bf0a357076ae17b8ef02636830 100644 (file)
@@ -27,8 +27,8 @@ use std::sync::Arc;
 use magical_bitcoin_wallet::bitcoin;
 use magical_bitcoin_wallet::database::MemoryDatabase;
 use magical_bitcoin_wallet::descriptor::HDKeyPaths;
-use magical_bitcoin_wallet::types::ScriptType;
 use magical_bitcoin_wallet::wallet::address_validator::{AddressValidator, AddressValidatorError};
+use magical_bitcoin_wallet::ScriptType;
 use magical_bitcoin_wallet::{OfflineWallet, Wallet};
 
 use bitcoin::hashes::hex::FromHex;
index 5b078dd2e5ff4701ab8ba35b999ad356635c40d3..4b2940460b9dd77fdca93a6061dc44232d164f41 100644 (file)
@@ -23,6 +23,7 @@
 // SOFTWARE.
 
 use std::collections::HashSet;
+use std::fmt;
 use std::path::Path;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::{Arc, Mutex};
@@ -116,7 +117,7 @@ impl CompactFilters {
         })
     }
 
-    fn process_tx<D: BatchDatabase + DatabaseUtils>(
+    fn process_tx<D: BatchDatabase>(
         &self,
         database: &mut D,
         tx: &Transaction,
@@ -207,7 +208,7 @@ impl OnlineBlockchain for CompactFiltersBlockchain {
         vec![Capability::FullHistory].into_iter().collect()
     }
 
-    fn setup<D: BatchDatabase + DatabaseUtils, P: 'static + Progress>(
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
         &self,
         _stop_gap: Option<usize>, // TODO: move to electrum and esplora only
         database: &mut D,
@@ -460,6 +461,14 @@ pub enum CompactFiltersError {
     Global(Box<crate::error::Error>),
 }
 
+impl fmt::Display for CompactFiltersError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for CompactFiltersError {}
+
 macro_rules! impl_error {
     ( $from:ty, $to:ident ) => {
         impl std::convert::From<$from> for CompactFiltersError {
index c6459ce4090962668096c8bf4c0ce8bed046369a..a317b3eacff1b7e4b5d35a9cc4048c81da2f7790 100644 (file)
@@ -257,7 +257,7 @@ impl Peer {
         *self.connected.read().unwrap()
     }
 
-    pub fn reader_thread(
+    fn reader_thread(
         network: Network,
         connection: TcpStream,
         reader_thread_responses: Arc<RwLock<ResponsesMap>>,
index 3bb9e6bb4d8c1a5405bf8e0520d553923a4a5d69..6dc8683c8f3f18bbb95c8276ed468a326f537908 100644 (file)
@@ -33,7 +33,7 @@ use electrum_client::{Client, ElectrumApi};
 
 use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
 use super::*;
-use crate::database::{BatchDatabase, DatabaseUtils};
+use crate::database::BatchDatabase;
 use crate::error::Error;
 use crate::FeeRate;
 
@@ -73,7 +73,7 @@ impl OnlineBlockchain for ElectrumBlockchain {
         .collect()
     }
 
-    fn setup<D: BatchDatabase + DatabaseUtils, P: Progress>(
+    fn setup<D: BatchDatabase, P: Progress>(
         &self,
         stop_gap: Option<usize>,
         database: &mut D,
index 059f543b931ba5684caca930813c44a3ac84a0bf..65c2a3405fd7b7602ba3ecabc510ca4234ef11c2 100644 (file)
@@ -23,6 +23,7 @@
 // SOFTWARE.
 
 use std::collections::{HashMap, HashSet};
+use std::fmt;
 
 use futures::stream::{self, StreamExt, TryStreamExt};
 
@@ -92,7 +93,7 @@ impl OnlineBlockchain for EsploraBlockchain {
         .collect()
     }
 
-    fn setup<D: BatchDatabase + DatabaseUtils, P: Progress>(
+    fn setup<D: BatchDatabase, P: Progress>(
         &self,
         stop_gap: Option<usize>,
         database: &mut D,
@@ -358,6 +359,14 @@ pub enum EsploraError {
     TransactionNotFound(Txid),
 }
 
+impl fmt::Display for EsploraError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for EsploraError {}
+
 impl From<reqwest::Error> for EsploraError {
     fn from(other: reqwest::Error) -> Self {
         EsploraError::Reqwest(other)
index 1692ccabead8e6a00ad0e568fb50a3a7de1265c2..98b2161dd3a088247ffc69230d6e5edda6527200 100644 (file)
@@ -29,24 +29,29 @@ use std::sync::Arc;
 
 use bitcoin::{Transaction, Txid};
 
-use crate::database::{BatchDatabase, DatabaseUtils};
+use crate::database::BatchDatabase;
 use crate::error::Error;
 use crate::FeeRate;
 
-pub mod utils;
+pub(crate) mod utils;
 
 #[cfg(feature = "electrum")]
+#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
 pub mod electrum;
 #[cfg(feature = "electrum")]
 pub use self::electrum::ElectrumBlockchain;
 
 #[cfg(feature = "esplora")]
+#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
 pub mod esplora;
 #[cfg(feature = "esplora")]
 pub use self::esplora::EsploraBlockchain;
 
 #[cfg(feature = "compact_filters")]
+#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
 pub mod compact_filters;
+#[cfg(feature = "compact_filters")]
+pub use self::compact_filters::CompactFiltersBlockchain;
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum Capability {
@@ -76,13 +81,13 @@ impl Blockchain for OfflineBlockchain {
 pub trait OnlineBlockchain: Blockchain {
     fn get_capabilities(&self) -> HashSet<Capability>;
 
-    fn setup<D: BatchDatabase + DatabaseUtils, P: 'static + Progress>(
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
         &self,
         stop_gap: Option<usize>,
         database: &mut D,
         progress_update: P,
     ) -> Result<(), Error>;
-    fn sync<D: BatchDatabase + DatabaseUtils, P: 'static + Progress>(
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
         &self,
         stop_gap: Option<usize>,
         database: &mut D,
@@ -163,7 +168,7 @@ impl<T: OnlineBlockchain> OnlineBlockchain for Arc<T> {
         maybe_await!(self.deref().get_capabilities())
     }
 
-    fn setup<D: BatchDatabase + DatabaseUtils, P: 'static + Progress>(
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
         &self,
         stop_gap: Option<usize>,
         database: &mut D,
@@ -172,7 +177,7 @@ impl<T: OnlineBlockchain> OnlineBlockchain for Arc<T> {
         maybe_await!(self.deref().setup(stop_gap, database, progress_update))
     }
 
-    fn sync<D: BatchDatabase + DatabaseUtils, P: 'static + Progress>(
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
         &self,
         stop_gap: Option<usize>,
         database: &mut D,
index 016d5e27344318d59fbe609c0d0226af5200e85f..63bd5a7b4948f7fddfe4b7aa45da587eba5d3ed4 100644 (file)
@@ -67,7 +67,7 @@ pub trait ElectrumLikeSync {
 
     // Provided methods down here...
 
-    fn electrum_like_setup<D: BatchDatabase + DatabaseUtils, P: Progress>(
+    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
         &self,
         stop_gap: Option<usize>,
         database: &mut D,
@@ -196,7 +196,7 @@ pub trait ElectrumLikeSync {
         Ok(())
     }
 
-    fn check_tx_and_descendant<D: DatabaseUtils + BatchDatabase>(
+    fn check_tx_and_descendant<D: BatchDatabase>(
         &self,
         database: &mut D,
         txid: &Txid,
@@ -320,7 +320,7 @@ pub trait ElectrumLikeSync {
         Ok(to_check_later)
     }
 
-    fn check_history<D: DatabaseUtils + BatchDatabase>(
+    fn check_history<D: BatchDatabase>(
         &self,
         database: &mut D,
         script_pubkey: Script,
index f3b11ef6e20e848527b40b54d0cd02d11129c550..51c56ef910af59350d0e8ea3832efa76dec7721a 100644 (file)
@@ -40,7 +40,7 @@ use crate::error::Error;
 use crate::types::ScriptType;
 use crate::{FeeRate, TxBuilder, Wallet};
 
-fn parse_addressee(s: &str) -> Result<(Address, u64), String> {
+fn parse_recipient(s: &str) -> Result<(Address, u64), String> {
     let parts: Vec<_> = s.split(":").collect();
     if parts.len() != 2 {
         return Err("Invalid format".to_string());
@@ -62,8 +62,8 @@ fn parse_outpoint(s: &str) -> Result<OutPoint, String> {
     OutPoint::from_str(s).map_err(|e| format!("{:?}", e))
 }
 
-fn addressee_validator(s: String) -> Result<(), String> {
-    parse_addressee(&s).map(|_| ())
+fn recipient_validator(s: String) -> Result<(), String> {
+    parse_recipient(&s).map(|_| ())
 }
 
 fn outpoint_validator(s: String) -> Result<(), String> {
@@ -95,18 +95,18 @@ pub fn make_cli_subcommands<'a, 'b>() -> App<'a, 'b> {
                     Arg::with_name("to")
                         .long("to")
                         .value_name("ADDRESS:SAT")
-                        .help("Adds an addressee to the transaction")
+                        .help("Adds a recipient to the transaction")
                         .takes_value(true)
                         .number_of_values(1)
                         .required(true)
                         .multiple(true)
-                        .validator(addressee_validator),
+                        .validator(recipient_validator),
                 )
                 .arg(
                     Arg::with_name("send_all")
                         .short("all")
                         .long("send_all")
-                        .help("Sends all the funds (or all the selected utxos). Requires only one addressees of value 0"),
+                        .help("Sends all the funds (or all the selected utxos). Requires only one recipients of value 0"),
                 )
                 .arg(
                     Arg::with_name("enable_rbf")
@@ -382,13 +382,13 @@ where
             "satoshi": wallet.get_balance()?
         }))
     } else if let Some(sub_matches) = matches.subcommand_matches("create_tx") {
-        let addressees = sub_matches
+        let recipients = sub_matches
             .values_of("to")
             .unwrap()
-            .map(|s| parse_addressee(s))
+            .map(|s| parse_recipient(s))
             .collect::<Result<Vec<_>, _>>()
             .map_err(|s| Error::Generic(s))?;
-        let mut tx_builder = TxBuilder::from_addressees(addressees);
+        let mut tx_builder = TxBuilder::with_recipients(recipients);
 
         if sub_matches.is_present("send_all") {
             tx_builder = tx_builder.send_all();
@@ -503,13 +503,13 @@ where
         }))
     } else if let Some(sub_matches) = matches.subcommand_matches("finalize_psbt") {
         let psbt = base64::decode(&sub_matches.value_of("psbt").unwrap()).unwrap();
-        let mut psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
+        let psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap();
 
         let assume_height = sub_matches
             .value_of("assume_height")
             .and_then(|s| Some(s.parse().unwrap()));
 
-        let finalized = wallet.finalize_psbt(&mut psbt, assume_height)?;
+        let (psbt, finalized) = wallet.finalize_psbt(psbt, assume_height)?;
         Ok(json!({
             "psbt": base64::encode(&serialize(&psbt)),
             "is_finalized": finalized,
index dab4279af17058dc91b554c6612f1243e92ae929..c91b385eed463393e3b758a7be5b924b7ab4e7c3 100644 (file)
@@ -28,10 +28,10 @@ use bitcoin::{OutPoint, Script, Transaction, TxOut};
 use crate::error::Error;
 use crate::types::*;
 
-#[cfg(any(feature = "key-value-db", feature = "default"))]
-pub mod keyvalue;
-pub mod memory;
+#[cfg(feature = "key-value-db")]
+pub(crate) mod keyvalue;
 
+pub mod memory;
 pub use memory::MemoryDatabase;
 
 pub trait BatchOperations {
@@ -102,7 +102,7 @@ pub trait BatchDatabase: Database {
     fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
 }
 
-pub trait DatabaseUtils: Database {
+pub(crate) trait DatabaseUtils: Database {
     fn is_mine(&self, script: &Script) -> Result<bool, Error> {
         self.get_path_from_script_pubkey(script)
             .map(|o| o.is_some())
index 5d32b5de872cc798b37ebcfbf631e596adc750b8..08bc2baae8ffe5d76cfacaae95e264fd97c9d6ea 100644 (file)
@@ -53,6 +53,8 @@ impl std::fmt::Display for Error {
     }
 }
 
+impl std::error::Error for Error {}
+
 impl_error!(bitcoin::util::bip32::Error, BIP32);
 impl_error!(bitcoin::util::base58::Error, Base58);
 impl_error!(bitcoin::util::key::Error, PK);
index 42bf5eb17fd53ab6be2ff77ad912bc46b7cf646f..c8834bd502676d1e0290034fd2a3fc67c98bd13e 100644 (file)
@@ -24,6 +24,7 @@
 
 use std::cmp::max;
 use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::fmt;
 use std::sync::Arc;
 
 use serde::ser::SerializeMap;
@@ -423,8 +424,16 @@ pub enum PolicyError {
     IncompatibleConditions,
 }
 
+impl fmt::Display for PolicyError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for PolicyError {}
+
 impl Policy {
-    pub fn new(item: SatisfiableItem) -> Self {
+    fn new(item: SatisfiableItem) -> Self {
         Policy {
             id: item.id(),
             item,
@@ -433,7 +442,7 @@ impl Policy {
         }
     }
 
-    pub fn make_and(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
+    fn make_and(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
         match (a, b) {
             (None, None) => Ok(None),
             (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
@@ -441,7 +450,7 @@ impl Policy {
         }
     }
 
-    pub fn make_or(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
+    fn make_or(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
         match (a, b) {
             (None, None) => Ok(None),
             (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
@@ -449,10 +458,7 @@ impl Policy {
         }
     }
 
-    pub fn make_thresh(
-        items: Vec<Policy>,
-        threshold: usize,
-    ) -> Result<Option<Policy>, PolicyError> {
+    fn make_thresh(items: Vec<Policy>, threshold: usize) -> Result<Option<Policy>, PolicyError> {
         if threshold == 0 {
             return Ok(None);
         }
index 1bd6272e3b47064ff039efc16b781eb698884131..7bee83ff78911652ca2f783d0e953799d655f28c 100644 (file)
@@ -43,7 +43,9 @@ pub enum Error {
     TransactionNotFound,
     TransactionConfirmed,
     IrreplaceableTransaction,
-    FeeRateTooLow(crate::wallet::utils::FeeRate),
+    FeeRateTooLow {
+        required: crate::types::FeeRate,
+    },
 
     ChecksumMismatch,
     DifferentDescriptorStructure,
index 7de7c20d5189a0753b1f597a6dfa8fe31548f660..433a201d59c0989429bc2301ae584d79bc363655 100644 (file)
@@ -24,7 +24,7 @@
 
 // only enables the `doc_cfg` feature when
 // the `docsrs` configuration attribute is defined
-#[cfg_attr(docsrs, feature(doc_cfg))]
+#![cfg_attr(docsrs, feature(doc_cfg))]
 
 pub extern crate bitcoin;
 extern crate log;
@@ -45,13 +45,9 @@ extern crate lazy_static;
 
 #[cfg(feature = "electrum")]
 pub extern crate electrum_client;
-#[cfg(feature = "electrum")]
-pub use electrum_client::client::Client;
 
 #[cfg(feature = "esplora")]
 pub extern crate reqwest;
-#[cfg(feature = "esplora")]
-pub use blockchain::esplora::EsploraBlockchain;
 
 #[cfg(feature = "key-value-db")]
 pub extern crate sled;
@@ -74,11 +70,19 @@ pub mod error;
 pub mod blockchain;
 pub mod database;
 pub mod descriptor;
-pub mod psbt;
-pub mod types;
+pub(crate) mod psbt;
+pub(crate) mod types;
 pub mod wallet;
 
-pub use descriptor::ExtendedDescriptor;
+pub use error::Error;
+pub use types::*;
+pub use wallet::address_validator;
+pub use wallet::signer;
 pub use wallet::tx_builder::TxBuilder;
-pub use wallet::utils::FeeRate;
 pub use wallet::{OfflineWallet, Wallet};
+
+#[cfg(feature = "esplora")]
+pub use blockchain::esplora::EsploraBlockchain;
+
+#[cfg(feature = "electrum")]
+pub use blockchain::electrum::ElectrumBlockchain;
index 83b32dc14bbf2cfb20fe2b1341d4fbebec9c86c9..08e7131cdb80226d15a2d50515cc9b31cb4e50a8 100644 (file)
@@ -58,6 +58,34 @@ impl AsRef<[u8]> for ScriptType {
     }
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+// Internally stored as satoshi/vbyte
+pub struct FeeRate(f32);
+
+impl FeeRate {
+    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
+        FeeRate(btc_per_kvb * 1e5)
+    }
+
+    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
+        FeeRate(sat_per_vb)
+    }
+
+    pub fn default_min_relay_fee() -> Self {
+        FeeRate(1.0)
+    }
+
+    pub fn as_sat_vb(&self) -> f32 {
+        self.0
+    }
+}
+
+impl std::default::Default for FeeRate {
+    fn default() -> Self {
+        FeeRate::default_min_relay_fee()
+    }
+}
+
 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
 pub struct UTXO {
     pub outpoint: OutPoint,
index fc1a58a1862ae131eec0a388322cef82f34104c2..a96df3e61e1888cae015e5976f51cfb94ac0c021 100644 (file)
@@ -22,6 +22,8 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 // SOFTWARE.
 
+use std::fmt;
+
 use bitcoin::Script;
 
 use crate::descriptor::HDKeyPaths;
@@ -35,6 +37,14 @@ pub enum AddressValidatorError {
     InvalidScript,
 }
 
+impl fmt::Display for AddressValidatorError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for AddressValidatorError {}
+
 pub trait AddressValidator {
     fn validate(
         &self,
@@ -81,7 +91,7 @@ mod test {
 
         let addr = testutils!(@external descriptors, 10);
         wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
     }
 }
index ab03ce156cbf11d346939b4d10bba344ffbea7ae..d68360472e7e14f1d8070f7b8e2f2d02e09a8f10 100644 (file)
@@ -26,14 +26,14 @@ use bitcoin::consensus::encode::serialize;
 use bitcoin::{Script, TxIn};
 
 use crate::error::Error;
-use crate::types::UTXO;
+use crate::types::{FeeRate, UTXO};
 
 pub type DefaultCoinSelectionAlgorithm = DumbCoinSelection;
 
 #[derive(Debug)]
 pub struct CoinSelectionResult {
     pub txin: Vec<(TxIn, Script)>,
-    pub total_amount: u64,
+    pub selected_amount: u64,
     pub fee_amount: f32,
 }
 
@@ -42,8 +42,8 @@ pub trait CoinSelectionAlgorithm: std::fmt::Debug {
         &self,
         utxos: Vec<UTXO>,
         use_all_utxos: bool,
-        fee_rate: f32,
-        outgoing_amount: u64,
+        fee_rate: FeeRate,
+        amount_needed: u64,
         input_witness_weight: usize,
         fee_amount: f32,
     ) -> Result<CoinSelectionResult, Error>;
@@ -57,16 +57,16 @@ impl CoinSelectionAlgorithm for DumbCoinSelection {
         &self,
         mut utxos: Vec<UTXO>,
         use_all_utxos: bool,
-        fee_rate: f32,
+        fee_rate: FeeRate,
         outgoing_amount: u64,
         input_witness_weight: usize,
         mut fee_amount: f32,
     ) -> Result<CoinSelectionResult, Error> {
         let mut txin = Vec::new();
-        let calc_fee_bytes = |wu| (wu as f32) * fee_rate / 4.0;
+        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
 
         log::debug!(
-            "outgoing_amount = `{}`, fee_amount = `{}`, fee_rate = `{}`",
+            "outgoing_amount = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
             outgoing_amount,
             fee_amount,
             fee_rate
@@ -75,11 +75,11 @@ impl CoinSelectionAlgorithm for DumbCoinSelection {
         // sort so that we pick them starting from the larger.
         utxos.sort_by(|a, b| a.txout.value.partial_cmp(&b.txout.value).unwrap());
 
-        let mut total_amount: u64 = 0;
-        while use_all_utxos || total_amount < outgoing_amount + (fee_amount.ceil() as u64) {
+        let mut selected_amount: u64 = 0;
+        while use_all_utxos || selected_amount < outgoing_amount + (fee_amount.ceil() as u64) {
             let utxo = match utxos.pop() {
                 Some(utxo) => utxo,
-                None if total_amount < outgoing_amount + (fee_amount.ceil() as u64) => {
+                None if selected_amount < outgoing_amount + (fee_amount.ceil() as u64) => {
                     return Err(Error::InsufficientFunds)
                 }
                 None if use_all_utxos => break,
@@ -100,13 +100,13 @@ impl CoinSelectionAlgorithm for DumbCoinSelection {
             );
 
             txin.push((new_in, utxo.txout.script_pubkey));
-            total_amount += utxo.txout.value;
+            selected_amount += utxo.txout.value;
         }
 
         Ok(CoinSelectionResult {
             txin,
             fee_amount,
-            total_amount,
+            selected_amount,
         })
     }
 }
@@ -154,11 +154,18 @@ mod test {
         let utxos = get_test_utxos();
 
         let result = DumbCoinSelection
-            .coin_select(utxos, false, 1.0, 250_000, P2WPKH_WITNESS_SIZE, 50.0)
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                250_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
             .unwrap();
 
         assert_eq!(result.txin.len(), 2);
-        assert_eq!(result.total_amount, 300_000);
+        assert_eq!(result.selected_amount, 300_000);
         assert_eq!(result.fee_amount, 186.0);
     }
 
@@ -167,11 +174,18 @@ mod test {
         let utxos = get_test_utxos();
 
         let result = DumbCoinSelection
-            .coin_select(utxos, true, 1.0, 20_000, P2WPKH_WITNESS_SIZE, 50.0)
+            .coin_select(
+                utxos,
+                true,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
             .unwrap();
 
         assert_eq!(result.txin.len(), 2);
-        assert_eq!(result.total_amount, 300_000);
+        assert_eq!(result.selected_amount, 300_000);
         assert_eq!(result.fee_amount, 186.0);
     }
 
@@ -180,11 +194,18 @@ mod test {
         let utxos = get_test_utxos();
 
         let result = DumbCoinSelection
-            .coin_select(utxos, false, 1.0, 20_000, P2WPKH_WITNESS_SIZE, 50.0)
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
             .unwrap();
 
         assert_eq!(result.txin.len(), 1);
-        assert_eq!(result.total_amount, 200_000);
+        assert_eq!(result.selected_amount, 200_000);
         assert_eq!(result.fee_amount, 118.0);
     }
 
@@ -194,7 +215,14 @@ mod test {
         let utxos = get_test_utxos();
 
         DumbCoinSelection
-            .coin_select(utxos, false, 1.0, 500_000, P2WPKH_WITNESS_SIZE, 50.0)
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                500_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
             .unwrap();
     }
 
@@ -204,7 +232,14 @@ mod test {
         let utxos = get_test_utxos();
 
         DumbCoinSelection
-            .coin_select(utxos, false, 1000.0, 250_000, P2WPKH_WITNESS_SIZE, 50.0)
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1000.0),
+                250_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
             .unwrap();
     }
 }
index 6f619931513c7388470a4bf65fa62981c85bd5e4..452b90eb851247a804bddaec5d1400aae3eda095 100644 (file)
@@ -45,12 +45,14 @@ mod rbf;
 pub mod signer;
 pub mod time;
 pub mod tx_builder;
-pub mod utils;
+pub(crate) mod utils;
+
+pub use utils::IsDust;
 
 use address_validator::AddressValidator;
 use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
 use tx_builder::TxBuilder;
-use utils::{After, FeeRate, IsDust, Older};
+use utils::{After, Older};
 
 use crate::blockchain::{Blockchain, OfflineBlockchain, OnlineBlockchain, Progress};
 use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
@@ -185,7 +187,7 @@ where
         &self,
         builder: TxBuilder<Cs>,
     ) -> Result<(PSBT, TransactionDetails), Error> {
-        if builder.addressees.is_empty() {
+        if builder.recipients.is_empty() {
             return Err(Error::NoAddressees);
         }
 
@@ -239,8 +241,8 @@ where
             output: vec![],
         };
 
-        let fee_rate = builder.fee_rate.unwrap_or_default().as_sat_vb();
-        if builder.send_all && builder.addressees.len() != 1 {
+        let fee_rate = builder.fee_rate.unwrap_or_default();
+        if builder.send_all && builder.recipients.len() != 1 {
             return Err(Error::SendAllMultipleOutputs);
         }
 
@@ -249,10 +251,10 @@ where
         let mut outgoing: u64 = 0;
         let mut received: u64 = 0;
 
-        let calc_fee_bytes = |wu| (wu as f32) * fee_rate / 4.0;
+        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
         fee_amount += calc_fee_bytes(tx.get_weight());
 
-        for (index, (address, satoshi)) in builder.addressees.iter().enumerate() {
+        for (index, (address, satoshi)) in builder.recipients.iter().enumerate() {
             let value = match builder.send_all {
                 true => 0,
                 false if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
@@ -304,7 +306,7 @@ where
         )?;
         let coin_selection::CoinSelectionResult {
             txin,
-            total_amount,
+            selected_amount,
             mut fee_amount,
         } = builder.coin_selection.coin_select(
             available_utxos,
@@ -342,7 +344,7 @@ where
         };
 
         let mut fee_amount = fee_amount.ceil() as u64;
-        let change_val = total_amount - outgoing - fee_amount;
+        let change_val = selected_amount - outgoing - fee_amount;
         if !builder.send_all && !change_val.is_dust() {
             let mut change_output = change_output.unwrap();
             change_output.value = change_val;
@@ -366,7 +368,7 @@ where
         }
 
         // sort input/outputs according to the chosen algorithm
-        builder.ordering.modify_tx(&mut tx);
+        builder.ordering.sort_tx(&mut tx);
 
         let txid = tx.txid();
         let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
@@ -376,7 +378,7 @@ where
             txid,
             timestamp: time::get_timestamp(),
             received,
-            sent: total_amount,
+            sent: selected_amount,
             fees: fee_amount,
             height: None,
         };
@@ -409,7 +411,9 @@ where
         let new_feerate = builder.fee_rate.unwrap_or_default();
 
         if new_feerate < required_feerate {
-            return Err(Error::FeeRateTooLow(required_feerate));
+            return Err(Error::FeeRateTooLow {
+                required: required_feerate,
+            });
         }
         let mut fee_difference =
             (new_feerate.as_sat_vb() * tx.get_weight() as f32 / 4.0).ceil() as u64 - details.fees;
@@ -515,12 +519,12 @@ where
                     )?;
                     let coin_selection::CoinSelectionResult {
                         txin,
-                        total_amount,
+                        selected_amount,
                         fee_amount,
                     } = builder.coin_selection.coin_select(
                         available_utxos,
                         use_all_utxos,
-                        new_feerate.as_sat_vb(),
+                        new_feerate,
                         fee_difference
                             .checked_sub(removed_change_output.value)
                             .unwrap_or(0),
@@ -538,8 +542,8 @@ where
                         .for_each(|i| i.sequence = tx.input[0].sequence);
                     tx.input.extend_from_slice(&mut txin);
 
-                    details.sent += total_amount;
-                    total_amount
+                    details.sent += selected_amount;
+                    selected_amount
                 } else {
                     // otherwise just remove the output and add 0 new coins
                     0
@@ -570,7 +574,7 @@ where
         }
 
         // sort input/outputs according to the chosen algorithm
-        builder.ordering.modify_tx(&mut tx);
+        builder.ordering.sort_tx(&mut tx);
 
         // TODO: check that we are not replacing more than 100 txs from mempool
 
@@ -620,9 +624,7 @@ where
         }
 
         // attempt to finalize
-        let finalized = self.finalize_psbt(&mut psbt, assume_height)?;
-
-        Ok((psbt, finalized))
+        self.finalize_psbt(psbt, assume_height)
     }
 
     pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error> {
@@ -650,9 +652,9 @@ where
 
     pub fn finalize_psbt(
         &self,
-        psbt: &mut PSBT,
+        mut psbt: PSBT,
         assume_height: Option<u32>,
-    ) -> Result<bool, Error> {
+    ) -> Result<(PSBT, bool), Error> {
         let mut tx = psbt.global.unsigned_tx.clone();
 
         for (n, (input, psbt_input)) in tx.input.iter_mut().zip(psbt.inputs.iter()).enumerate() {
@@ -696,7 +698,7 @@ where
                 desc
             } else {
                 debug!("Couldn't find the right derived descriptor for input {}", n);
-                return Ok(false);
+                return Ok((psbt, false));
             };
 
             match desc.satisfy(
@@ -710,7 +712,7 @@ where
                 Ok(_) => continue,
                 Err(e) => {
                     debug!("satisfy error {:?} for input {}", e, n);
-                    return Ok(false);
+                    return Ok((psbt, false));
                 }
             }
         }
@@ -721,7 +723,7 @@ where
             psbt_input.final_script_witness = Some(input.witness);
         }
 
-        Ok(true)
+        Ok((psbt, true))
     }
 
     // Internals
@@ -1236,10 +1238,10 @@ mod test {
 
     #[test]
     #[should_panic(expected = "NoAddressees")]
-    fn test_create_tx_empty_addressees() {
+    fn test_create_tx_empty_recipients() {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         wallet
-            .create_tx(TxBuilder::from_addressees(vec![]).version(0))
+            .create_tx(TxBuilder::with_recipients(vec![]).version(0))
             .unwrap();
     }
 
@@ -1249,7 +1251,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).version(0))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).version(0))
             .unwrap();
     }
 
@@ -1261,7 +1263,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
         wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).version(1))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).version(1))
             .unwrap();
     }
 
@@ -1270,7 +1272,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).version(42))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).version(42))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.version, 42);
@@ -1281,7 +1283,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
@@ -1292,7 +1294,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
@@ -1303,7 +1305,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).nlocktime(630_000))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).nlocktime(630_000))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
@@ -1314,7 +1316,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).nlocktime(630_000))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).nlocktime(630_000))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
@@ -1328,7 +1330,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
         wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).nlocktime(50000))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).nlocktime(50000))
             .unwrap();
     }
 
@@ -1337,7 +1339,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
@@ -1348,7 +1350,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).enable_rbf())
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).enable_rbf())
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFD);
@@ -1362,7 +1364,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
         let addr = wallet.get_new_address().unwrap();
         wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).enable_rbf_with_sequence(3))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).enable_rbf_with_sequence(3))
             .unwrap();
     }
 
@@ -1371,7 +1373,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
@@ -1384,7 +1386,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr, 25_000)])
+                TxBuilder::with_recipients(vec![(addr, 25_000)])
                     .enable_rbf_with_sequence(0xFFFFFFFE),
             )
             .unwrap();
@@ -1396,7 +1398,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr, 25_000)])
+                TxBuilder::with_recipients(vec![(addr, 25_000)])
                     .enable_rbf_with_sequence(0xDEADBEEF),
             )
             .unwrap();
@@ -1409,7 +1411,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
@@ -1424,7 +1426,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 25_000)]).do_not_spend_change(),
+                TxBuilder::with_recipients(vec![(addr.clone(), 25_000)]).do_not_spend_change(),
             )
             .unwrap();
     }
@@ -1436,7 +1438,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 25_000), (addr, 10_000)]).send_all(),
+                TxBuilder::with_recipients(vec![(addr.clone(), 25_000), (addr, 10_000)]).send_all(),
             )
             .unwrap();
     }
@@ -1446,7 +1448,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
@@ -1461,7 +1463,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
@@ -1473,7 +1475,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         let (psbt, details) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 0)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 0)])
                     .fee_rate(FeeRate::from_sat_per_vb(5.0))
                     .send_all(),
             )
@@ -1490,7 +1492,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         let (psbt, details) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 25_000)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 25_000)])
                     .ordering(TxOrdering::Untouched),
             )
             .unwrap();
@@ -1508,7 +1510,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 49_800)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 49_800)]))
             .unwrap();
 
         assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
@@ -1523,9 +1525,9 @@ mod test {
         // very high fee rate, so that the only output would be below dust
         wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 0)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 0)])
                     .send_all()
-                    .fee_rate(super::utils::FeeRate::from_sat_per_vb(453.0)),
+                    .fee_rate(crate::FeeRate::from_sat_per_vb(453.0)),
             )
             .unwrap();
     }
@@ -1536,7 +1538,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         let (psbt, details) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 30_000), (addr.clone(), 10_000)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 30_000), (addr.clone(), 10_000)])
                     .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic),
             )
             .unwrap();
@@ -1555,7 +1557,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 30_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 30_000)]))
             .unwrap();
 
         assert_eq!(psbt.inputs[0].sighash_type, Some(bitcoin::SigHashType::All));
@@ -1567,7 +1569,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 30_000)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 30_000)])
                     .sighash(bitcoin::SigHashType::Single),
             )
             .unwrap();
@@ -1586,7 +1588,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
@@ -1610,7 +1612,7 @@ mod test {
 
         let addr = testutils!(@external descriptors, 5);
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
@@ -1631,7 +1633,7 @@ mod test {
             get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert_eq!(
@@ -1654,7 +1656,7 @@ mod test {
             get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert_eq!(psbt.inputs[0].redeem_script, None);
@@ -1677,7 +1679,7 @@ mod test {
             get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         let script = Script::from(
@@ -1697,7 +1699,7 @@ mod test {
             get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert!(psbt.inputs[0].non_witness_utxo.is_some());
@@ -1710,7 +1712,7 @@ mod test {
             get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         assert!(psbt.inputs[0].non_witness_utxo.is_none());
@@ -1724,7 +1726,7 @@ mod test {
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 0)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 0)])
                     .force_non_witness_utxo()
                     .send_all(),
             )
@@ -1740,7 +1742,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, mut details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -1757,7 +1759,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, mut details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]))
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]))
             .unwrap();
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -1775,7 +1777,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = wallet.get_new_address().unwrap();
         let (psbt, mut details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr, 25_000)]).enable_rbf())
+            .create_tx(TxBuilder::with_recipients(vec![(addr, 25_000)]).enable_rbf())
             .unwrap();
         let tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -1796,7 +1798,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
         let (psbt, mut original_details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 25_000)]).enable_rbf())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 25_000)]).enable_rbf())
             .unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -1858,7 +1860,7 @@ mod test {
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
         let (psbt, mut original_details) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 0)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 0)])
                     .send_all()
                     .enable_rbf(),
             )
@@ -1912,7 +1914,7 @@ mod test {
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
         let (psbt, mut original_details) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 0)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 0)])
                     .utxos(vec![OutPoint {
                         txid: incoming_txid,
                         vout: 0,
@@ -1959,7 +1961,7 @@ mod test {
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
         let (psbt, mut original_details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 45_000)]).enable_rbf())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 45_000)]).enable_rbf())
             .unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2023,7 +2025,7 @@ mod test {
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
         let (psbt, mut original_details) = wallet
             .create_tx(
-                TxBuilder::from_addressees(vec![(addr.clone(), 0)])
+                TxBuilder::with_recipients(vec![(addr.clone(), 0)])
                     .send_all()
                     .add_utxo(OutPoint {
                         txid: incoming_txid,
@@ -2099,7 +2101,7 @@ mod test {
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
         let (psbt, mut original_details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 45_000)]).enable_rbf())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 45_000)]).enable_rbf())
             .unwrap();
         let mut tx = psbt.extract_tx();
         assert_eq!(tx.input.len(), 1);
@@ -2159,7 +2161,7 @@ mod test {
 
         let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
         let (psbt, mut original_details) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 45_000)]).enable_rbf())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 45_000)]).enable_rbf())
             .unwrap();
         let mut tx = psbt.extract_tx();
         let txid = tx.txid();
@@ -2224,7 +2226,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
@@ -2240,7 +2242,7 @@ mod test {
             get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
         let addr = wallet.get_new_address().unwrap();
         let (psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
@@ -2255,7 +2257,7 @@ mod test {
         let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
         let addr = wallet.get_new_address().unwrap();
         let (mut psbt, _) = wallet
-            .create_tx(TxBuilder::from_addressees(vec![(addr.clone(), 0)]).send_all())
+            .create_tx(TxBuilder::with_recipients(vec![(addr.clone(), 0)]).send_all())
             .unwrap();
 
         psbt.inputs[0].hd_keypaths.clear();
index 81524e05637bf0b4e4f9139f8df9da06d79ef81e..766f4bd27cab73a2281dabc9c6399ba780261846 100644 (file)
@@ -84,6 +84,14 @@ pub enum SignerError {
     MissingHDKeypath,
 }
 
+impl fmt::Display for SignerError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for SignerError {}
+
 /// Trait for signers
 pub trait Signer: fmt::Debug {
     fn sign(
@@ -92,9 +100,7 @@ pub trait Signer: fmt::Debug {
         input_index: Option<usize>,
     ) -> Result<(), SignerError>;
 
-    fn sign_whole_tx(&self) -> bool {
-        false
-    }
+    fn sign_whole_tx(&self) -> bool;
 
     fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
         None
@@ -128,6 +134,10 @@ impl Signer for DescriptorXKey<ExtendedPrivKey> {
         derived_key.private_key.sign(psbt, Some(input_index))
     }
 
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
     fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
         Some(DescriptorSecretKey::XPrv(self.clone()))
     }
@@ -176,6 +186,10 @@ impl Signer for PrivateKey {
         Ok(())
     }
 
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
     fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
         Some(DescriptorSecretKey::PrivKey(self.clone()))
     }
@@ -299,7 +313,7 @@ impl<Pk: MiniscriptKey> SignersContainer<Pk> {
     }
 }
 
-pub trait ComputeSighash {
+pub(crate) trait ComputeSighash {
     fn sighash(
         psbt: &psbt::PartiallySignedTransaction,
         input_index: usize,
index 7ab8c219a4f1c744755ac242def7dee3c06c86cd..0d0a77c73c31224cb8a87bfad32596cb19ac7b2a 100644 (file)
@@ -44,9 +44,9 @@ pub fn get_timestamp() -> u64 {
 }
 
 #[cfg(not(target_arch = "wasm32"))]
-pub struct Instant(SystemInstant);
+pub(crate) struct Instant(SystemInstant);
 #[cfg(target_arch = "wasm32")]
-pub struct Instant(Duration);
+pub(crate) struct Instant(Duration);
 
 impl Instant {
     #[cfg(not(target_arch = "wasm32"))]
index 8a6bf4c24dba239ad00e998e69f8b575864a0829..aab9951f327ed919337a4295280f2acbc7c64eda 100644 (file)
@@ -28,12 +28,11 @@ use std::default::Default;
 use bitcoin::{Address, OutPoint, SigHashType, Transaction};
 
 use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
-use super::utils::FeeRate;
-use crate::types::UTXO;
+use crate::types::{FeeRate, UTXO};
 
 #[derive(Debug, Default)]
 pub struct TxBuilder<Cs: CoinSelectionAlgorithm> {
-    pub(crate) addressees: Vec<(Address, u64)>,
+    pub(crate) recipients: Vec<(Address, u64)>,
     pub(crate) send_all: bool,
     pub(crate) fee_rate: Option<FeeRate>,
     pub(crate) policy_path: Option<BTreeMap<String, Vec<usize>>>,
@@ -54,19 +53,19 @@ impl TxBuilder<DefaultCoinSelectionAlgorithm> {
         Self::default()
     }
 
-    pub fn from_addressees(addressees: Vec<(Address, u64)>) -> Self {
-        Self::default().set_addressees(addressees)
+    pub fn with_recipients(recipients: Vec<(Address, u64)>) -> Self {
+        Self::default().set_recipients(recipients)
     }
 }
 
 impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
-    pub fn set_addressees(mut self, addressees: Vec<(Address, u64)>) -> Self {
-        self.addressees = addressees;
+    pub fn set_recipients(mut self, recipients: Vec<(Address, u64)>) -> Self {
+        self.recipients = recipients;
         self
     }
 
-    pub fn add_addressee(mut self, address: Address, amount: u64) -> Self {
-        self.addressees.push((address, amount));
+    pub fn add_recipient(mut self, address: Address, amount: u64) -> Self {
+        self.recipients.push((address, amount));
         self
     }
 
@@ -158,7 +157,7 @@ impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
 
     pub fn coin_selection<P: CoinSelectionAlgorithm>(self, coin_selection: P) -> TxBuilder<P> {
         TxBuilder {
-            addressees: self.addressees,
+            recipients: self.recipients,
             send_all: self.send_all,
             fee_rate: self.fee_rate,
             policy_path: self.policy_path,
@@ -190,7 +189,7 @@ impl Default for TxOrdering {
 }
 
 impl TxOrdering {
-    pub fn modify_tx(&self, tx: &mut Transaction) {
+    pub fn sort_tx(&self, tx: &mut Transaction) {
         match self {
             TxOrdering::Untouched => {}
             TxOrdering::Shuffle => {
@@ -279,7 +278,7 @@ mod test {
         let original_tx = ordering_test_tx!();
         let mut tx = original_tx.clone();
 
-        TxOrdering::Untouched.modify_tx(&mut tx);
+        TxOrdering::Untouched.sort_tx(&mut tx);
 
         assert_eq!(original_tx, tx);
     }
@@ -289,7 +288,7 @@ mod test {
         let original_tx = ordering_test_tx!();
         let mut tx = original_tx.clone();
 
-        TxOrdering::Shuffle.modify_tx(&mut tx);
+        TxOrdering::Shuffle.sort_tx(&mut tx);
 
         assert_eq!(original_tx.input, tx.input);
         assert_ne!(original_tx.output, tx.output);
@@ -302,7 +301,7 @@ mod test {
         let original_tx = ordering_test_tx!();
         let mut tx = original_tx.clone();
 
-        TxOrdering::BIP69Lexicographic.modify_tx(&mut tx);
+        TxOrdering::BIP69Lexicographic.sort_tx(&mut tx);
 
         assert_eq!(
             tx.input[0].previous_output,
index 08444087bf48c199858d3a91e28c857874ffc385..bdf98364ca2cba759b4b0af97cf87e5de8d76d64 100644 (file)
@@ -40,34 +40,6 @@ impl IsDust for u64 {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
-// Internally stored as satoshi/vbyte
-pub struct FeeRate(f32);
-
-impl FeeRate {
-    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
-        FeeRate(btc_per_kvb * 1e5)
-    }
-
-    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
-        FeeRate(sat_per_vb)
-    }
-
-    pub fn default_min_relay_fee() -> Self {
-        FeeRate(1.0)
-    }
-
-    pub fn as_sat_vb(&self) -> f32 {
-        self.0
-    }
-}
-
-impl std::default::Default for FeeRate {
-    fn default() -> Self {
-        FeeRate::default_min_relay_fee()
-    }
-}
-
 pub struct After {
     pub current_height: Option<u32>,
     pub assume_height_reached: bool,
@@ -158,7 +130,7 @@ impl<I: Iterator> Iterator for ChunksIterator<I> {
 
 #[cfg(test)]
 mod test {
-    use super::*;
+    use crate::types::FeeRate;
 
     #[test]
     fn test_fee_from_btc_per_kb() {
index cb8d7374498ee1a67d878045860ca54f64645657..678473521ec2fea53de87c7fbdff48af09e16a00 100644 (file)
@@ -83,7 +83,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
                 use #root_ident::descriptor::ExtendedDescriptor;
                 use #root_ident::database::MemoryDatabase;
                 use #root_ident::types::ScriptType;
-                use #root_ident::{Wallet, TxBuilder};
+                use #root_ident::{Wallet, TxBuilder, FeeRate};
 
                 use super::*;
 
@@ -307,7 +307,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.create_tx(TxBuilder::from_addressees(vec![(node_addr, 25_000)])).unwrap();
+                    let (psbt, details) = wallet.create_tx(TxBuilder::with_recipients(vec![(node_addr, 25_000)])).unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     let tx = psbt.extract_tx();
@@ -334,7 +334,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.create_tx(TxBuilder::from_addressees(vec![(node_addr, 25_000)])).unwrap();
+                    let (psbt, details) = wallet.create_tx(TxBuilder::with_recipients(vec![(node_addr, 25_000)])).unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     let sent_txid = wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -373,7 +373,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
 
                     let mut total_sent = 0;
                     for _ in 0..5 {
-                        let (psbt, details) = wallet.create_tx(TxBuilder::from_addressees(vec![(node_addr.clone(), 5_000)])).unwrap();
+                        let (psbt, details) = wallet.create_tx(TxBuilder::with_recipients(vec![(node_addr.clone(), 5_000)])).unwrap();
                         let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                         assert!(finalized, "Cannot finalize transaction");
                         wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -405,7 +405,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.create_tx(TxBuilder::from_addressees(vec![(node_addr.clone(), 5_000)]).enable_rbf()).unwrap();
+                    let (psbt, details) = wallet.create_tx(TxBuilder::with_recipients(vec![(node_addr.clone(), 5_000)]).enable_rbf()).unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -437,7 +437,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 50_000);
 
-                    let (psbt, details) = wallet.create_tx(TxBuilder::from_addressees(vec![(node_addr.clone(), 49_000)]).enable_rbf()).unwrap();
+                    let (psbt, details) = wallet.create_tx(TxBuilder::with_recipients(vec![(node_addr.clone(), 49_000)]).enable_rbf()).unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -470,7 +470,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 75_000);
 
-                    let (psbt, details) = wallet.create_tx(TxBuilder::from_addressees(vec![(node_addr.clone(), 49_000)]).enable_rbf()).unwrap();
+                    let (psbt, details) = wallet.create_tx(TxBuilder::with_recipients(vec![(node_addr.clone(), 49_000)]).enable_rbf()).unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();
@@ -501,7 +501,7 @@ pub fn magical_blockchain_tests(attr: TokenStream, item: TokenStream) -> TokenSt
                     wallet.sync(noop_progress(), None).unwrap();
                     assert_eq!(wallet.get_balance().unwrap(), 75_000);
 
-                    let (psbt, details) = wallet.create_tx(TxBuilder::from_addressees(vec![(node_addr.clone(), 49_000)]).enable_rbf()).unwrap();
+                    let (psbt, details) = wallet.create_tx(TxBuilder::with_recipients(vec![(node_addr.clone(), 49_000)]).enable_rbf()).unwrap();
                     let (psbt, finalized) = wallet.sign(psbt, None).unwrap();
                     assert!(finalized, "Cannot finalize transaction");
                     wallet.broadcast(psbt.extract_tx()).unwrap();