From 4a23070cc8ba64262c231733bd1c2bd1e82b7c29 Mon Sep 17 00:00:00 2001 From: Alekos Filini Date: Fri, 4 Jun 2021 14:55:25 +0200 Subject: [PATCH 1/4] [ci] Check fmt for examples/doctests --- .github/workflows/cont_integration.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index fe4a97e1..d33d48b2 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -162,7 +162,7 @@ jobs: - name: Checkout uses: actions/checkout@v2 - name: Set default toolchain - run: rustup default 1.51.0 # STABLE + run: rustup default nightly - name: Set profile run: rustup set profile minimal - name: Add rustfmt @@ -170,4 +170,4 @@ jobs: - name: Update toolchain run: rustup update - name: Check fmt - run: cargo fmt --all -- --check + run: cargo fmt --all -- --config format_code_in_doc_comments=true --check From 224be27aa8242b0c02d937c7a4a198b205789bf3 Mon Sep 17 00:00:00 2001 From: Alekos Filini Date: Fri, 4 Jun 2021 15:53:15 +0200 Subject: [PATCH 2/4] Fix example/doctests format --- src/descriptor/template.rs | 2 +- src/keys/mod.rs | 10 +++++----- src/wallet/coin_selection.rs | 29 ++++++++++++++++++----------- src/wallet/tx_builder.rs | 14 +++++++++----- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/descriptor/template.rs b/src/descriptor/template.rs index bba756c1..9b5d025e 100644 --- a/src/descriptor/template.rs +++ b/src/descriptor/template.rs @@ -37,7 +37,7 @@ pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks); /// /// ``` /// use bdk::descriptor::error::Error as DescriptorError; -/// use bdk::keys::{KeyError, IntoDescriptorKey}; +/// use bdk::keys::{IntoDescriptorKey, KeyError}; /// use bdk::miniscript::Legacy; /// use bdk::template::{DescriptorTemplate, DescriptorTemplateOut}; /// diff --git a/src/keys/mod.rs b/src/keys/mod.rs index 36ba2c40..1fbeada7 100644 --- a/src/keys/mod.rs +++ b/src/keys/mod.rs @@ -192,7 +192,7 @@ impl ExtScriptContext for Ctx { /// ``` /// use bdk::bitcoin::PublicKey; /// -/// use bdk::keys::{DescriptorKey, KeyError, ScriptContext, IntoDescriptorKey}; +/// use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError, ScriptContext}; /// /// pub struct MyKeyType { /// pubkey: PublicKey, @@ -211,8 +211,8 @@ impl ExtScriptContext for Ctx { /// use bdk::bitcoin::PublicKey; /// /// use bdk::keys::{ -/// mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError, -/// ScriptContext, IntoDescriptorKey, +/// mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, +/// IntoDescriptorKey, KeyError, ScriptContext, /// }; /// /// pub struct MyKeyType { @@ -237,7 +237,7 @@ impl ExtScriptContext for Ctx { /// ``` /// use bdk::bitcoin::PublicKey; /// -/// use bdk::keys::{DescriptorKey, ExtScriptContext, KeyError, ScriptContext, IntoDescriptorKey}; +/// use bdk::keys::{DescriptorKey, ExtScriptContext, IntoDescriptorKey, KeyError, ScriptContext}; /// /// pub struct MyKeyType { /// is_legacy: bool, @@ -266,7 +266,7 @@ impl ExtScriptContext for Ctx { /// use bdk::bitcoin::PublicKey; /// use std::str::FromStr; /// -/// use bdk::keys::{DescriptorKey, KeyError, IntoDescriptorKey}; +/// use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError}; /// /// pub struct MySegwitOnlyKeyType { /// pubkey: PublicKey, diff --git a/src/wallet/coin_selection.rs b/src/wallet/coin_selection.rs index f2e2ca5f..e3729bbc 100644 --- a/src/wallet/coin_selection.rs +++ b/src/wallet/coin_selection.rs @@ -46,17 +46,25 @@ //! let mut selected_amount = 0; //! let mut additional_weight = 0; //! let all_utxos_selected = required_utxos -//! .into_iter().chain(optional_utxos) -//! .scan((&mut selected_amount, &mut additional_weight), |(selected_amount, additional_weight), weighted_utxo| { -//! **selected_amount += weighted_utxo.utxo.txout().value; -//! **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight; -//! Some(weighted_utxo.utxo) -//! }) +//! .into_iter() +//! .chain(optional_utxos) +//! .scan( +//! (&mut selected_amount, &mut additional_weight), +//! |(selected_amount, additional_weight), weighted_utxo| { +//! **selected_amount += weighted_utxo.utxo.txout().value; +//! **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight; +//! Some(weighted_utxo.utxo) +//! }, +//! ) //! .collect::>(); //! let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0; -//! let amount_needed_with_fees = (fee_amount + additional_fees).ceil() as u64 + amount_needed; -//! if amount_needed_with_fees > selected_amount { -//! return Err(bdk::Error::InsufficientFunds{ needed: amount_needed_with_fees, available: selected_amount }); +//! let amount_needed_with_fees = +//! (fee_amount + additional_fees).ceil() as u64 + amount_needed; +//! if amount_needed_with_fees > selected_amount { +//! return Err(bdk::Error::InsufficientFunds { +//! needed: amount_needed_with_fees, +//! available: selected_amount, +//! }); //! } //! //! Ok(CoinSelectionResult { @@ -72,8 +80,7 @@ //! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap(); //! let (psbt, details) = { //! let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything); -//! builder -//! .add_recipient(to_address.script_pubkey(), 50_000); +//! builder.add_recipient(to_address.script_pubkey(), 50_000); //! builder.finish()? //! }; //! diff --git a/src/wallet/tx_builder.rs b/src/wallet/tx_builder.rs index f7eb6c59..92718c88 100644 --- a/src/wallet/tx_builder.rs +++ b/src/wallet/tx_builder.rs @@ -87,9 +87,9 @@ impl TxBuilderContext for BumpFee {} /// let (psbt1, details) = { /// let mut builder = wallet.build_tx(); /// builder -/// .ordering(TxOrdering::Untouched) -/// .add_recipient(addr1.script_pubkey(), 50_000) -/// .add_recipient(addr2.script_pubkey(), 50_000); +/// .ordering(TxOrdering::Untouched) +/// .add_recipient(addr1.script_pubkey(), 50_000) +/// .add_recipient(addr2.script_pubkey(), 50_000); /// builder.finish()? /// }; /// @@ -103,7 +103,10 @@ impl TxBuilderContext for BumpFee {} /// builder.finish()? /// }; /// -/// assert_eq!(psbt1.global.unsigned_tx.output[..2], psbt2.global.unsigned_tx.output[..2]); +/// assert_eq!( +/// psbt1.global.unsigned_tx.output[..2], +/// psbt2.global.unsigned_tx.output[..2] +/// ); /// # Ok::<(), bdk::Error>(()) /// ``` /// @@ -246,7 +249,8 @@ impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderConte /// let mut path = BTreeMap::new(); /// path.insert("aabbccdd".to_string(), vec![0, 1]); /// - /// let builder = wallet.build_tx() + /// let builder = wallet + /// .build_tx() /// .add_recipient(to_address.script_pubkey(), 50_000) /// .policy_path(path, KeychainKind::External); /// From 378167efcadffe67f6aae3f261f81955e8a8cbec Mon Sep 17 00:00:00 2001 From: Alekos Filini Date: Wed, 9 Jun 2021 11:09:57 +0200 Subject: [PATCH 3/4] Remove explicit `feature(external_doc)` It looks like this is now enabled by default as of `cargo 1.54.0-nightly (0cecbd673 2021-06-01)` --- src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 77cbef61..756e4429 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,9 +14,6 @@ // only enables the `doc_cfg` feature when // the `docsrs` configuration attribute is defined #![cfg_attr(docsrs, feature(doc_cfg))] -// only enables the nightly `external_doc` feature when -// `test-md-docs` is enabled -#![cfg_attr(feature = "test-md-docs", feature(external_doc))] //! A modern, lightweight, descriptor-based wallet library written in Rust. //! From 3b446c9e1425cea3ed8e38eec7f27b8247e99db0 Mon Sep 17 00:00:00 2001 From: Tobin Harding Date: Tue, 11 May 2021 11:10:54 +1000 Subject: [PATCH 4/4] Use no_run instead of ignore We have an attribute `no_run` that builds but does not run example code in Rustdocs, this keeps the examples building as the codebase evolves. use `no_run` and fix example code so it builds cleanly during test run. Some examples that require the `electrum` feature to be available have been feature-gated to make sure they aren't accidentally compiled when that feature is not enabled. Co-authored-by: Alekos Filini --- src/lib.rs | 161 ++++++++++++++++++++++++++++------------------------- 1 file changed, 84 insertions(+), 77 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 756e4429..284e49b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,34 +42,37 @@ //! ```toml //! bdk = "0.7.0" //! ``` -//! -//! ## Sync the balance of a descriptor -//! -//! ### Example -//! ```ignore -//! use bdk::Wallet; -//! use bdk::database::MemoryDatabase; -//! use bdk::blockchain::{noop_progress, ElectrumBlockchain}; -//! -//! use bdk::electrum_client::Client; -//! -//! fn main() -> Result<(), bdk::Error> { -//! let client = Client::new("ssl://electrum.blockstream.info:60002")?; -//! let wallet = Wallet::new( -//! "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", -//! Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"), -//! bitcoin::Network::Testnet, -//! MemoryDatabase::default(), -//! ElectrumBlockchain::from(client) -//! )?; -//! -//! wallet.sync(noop_progress(), None)?; -//! -//! println!("Descriptor balance: {} SAT", wallet.get_balance()?); -//! -//! Ok(()) -//! } -//! ``` +#![cfg_attr( + feature = "electrum", + doc = r##" +## Sync the balance of a descriptor + +### Example +```no_run +use bdk::Wallet; +use bdk::database::MemoryDatabase; +use bdk::blockchain::{noop_progress, ElectrumBlockchain}; +use bdk::electrum_client::Client; + +fn main() -> Result<(), bdk::Error> { + let client = Client::new("ssl://electrum.blockstream.info:60002")?; + let wallet = Wallet::new( + "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", + Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"), + bitcoin::Network::Testnet, + MemoryDatabase::default(), + ElectrumBlockchain::from(client) + )?; + + wallet.sync(noop_progress(), None)?; + + println!("Descriptor balance: {} SAT", wallet.get_balance()?); + + Ok(()) +} +``` +"## +)] //! //! ## Generate a few addresses //! @@ -94,61 +97,65 @@ //! Ok(()) //! } //! ``` -//! -//! ## Create a transaction -//! -//! ### Example -//! ```ignore -//! use base64::decode; -//! use bdk::{FeeRate, Wallet}; -//! use bdk::database::MemoryDatabase; -//! use bdk::blockchain::{noop_progress, ElectrumBlockchain}; -//! -//! use bdk::electrum_client::Client; -//! -//! use bitcoin::consensus::serialize; -//! use bdk::wallet::AddressIndex::New; -//! -//! fn main() -> Result<(), bdk::Error> { -//! let client = Client::new("ssl://electrum.blockstream.info:60002")?; -//! let wallet = Wallet::new( -//! "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", -//! Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"), -//! bitcoin::Network::Testnet, -//! MemoryDatabase::default(), -//! ElectrumBlockchain::from(client) -//! )?; -//! -//! wallet.sync(noop_progress(), None)?; -//! -//! let send_to = wallet.get_address(New)?; -//! let (psbt, details) = { -//! let mut builder = wallet.build_tx(); -//! builder -//! .add_recipient(send_to.script_pubkey(), 50_000) -//! .enable_rbf() -//! .do_not_spend_change() -//! .fee_rate(FeeRate::from_sat_per_vb(5.0)) -//! builder.finish()? -//! }; -//! -//! println!("Transaction details: {:#?}", details); -//! println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt))); -//! -//! Ok(()) -//! } -//! ``` +#![cfg_attr( + feature = "electrum", + doc = r##" +## Create a transaction + +### Example +```no_run +use base64::decode; + +use bdk::{FeeRate, Wallet}; +use bdk::database::MemoryDatabase; +use bdk::blockchain::{noop_progress, ElectrumBlockchain}; +use bdk::electrum_client::Client; + +use bitcoin::consensus::serialize; +use bdk::wallet::AddressIndex::New; + +fn main() -> Result<(), bdk::Error> { + let client = Client::new("ssl://electrum.blockstream.info:60002")?; + let wallet = Wallet::new( + "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", + Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"), + bitcoin::Network::Testnet, + MemoryDatabase::default(), + ElectrumBlockchain::from(client) + )?; + + wallet.sync(noop_progress(), None)?; + + let send_to = wallet.get_address(New)?; + let (psbt, details) = { + let mut builder = wallet.build_tx(); + builder + .add_recipient(send_to.script_pubkey(), 50_000) + .enable_rbf() + .do_not_spend_change() + .fee_rate(FeeRate::from_sat_per_vb(5.0)); + builder.finish()? + }; + + println!("Transaction details: {:#?}", details); + println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt))); + + Ok(()) +} +``` +"## +)] //! //! ## Sign a transaction //! //! ### Example -//! ```ignore +//! ```no_run //! use base64::decode; -//! use bdk::{Wallet}; -//! use bdk::database::MemoryDatabase; -//! //! use bitcoin::consensus::deserialize; //! +//! use bdk::{Wallet, SignOptions}; +//! use bdk::database::MemoryDatabase; +//! //! fn main() -> Result<(), bdk::Error> { //! let wallet = Wallet::new_offline( //! "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)", @@ -160,7 +167,7 @@ //! let psbt = "..."; //! let mut psbt = deserialize(&base64::decode(psbt).unwrap())?; //! -//! let finalized = wallet.sign(&mut psbt, None)?; +//! let finalized = wallet.sign(&mut psbt, SignOptions::default())?; //! //! Ok(()) //! }