From: github-actions Date: Tue, 14 Mar 2023 17:55:22 +0000 (+0000) Subject: Publish autogenerated nightly docs X-Git-Url: http://internal-gitweb-vhost/script/%22https:/database/scripts/struct.CommandStringError.html?a=commitdiff_plain;h=6c04165fca6fb6964218ca3839669cbbebc85768;p=bitcoindevkit.org Publish autogenerated nightly docs --- diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/all.html index 28de033bbc..98d156cd13 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/all.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/all.html @@ -1,2 +1 @@ -List of all items in this crate

List of all items

Structs

Enums

Traits

Macros

Functions

Type Definitions

\ No newline at end of file +List of all items in this crate

List of all items

Structs

Enums

Traits

Macros

Functions

Type Definitions

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html deleted file mode 100644 index 3336fe4b06..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html +++ /dev/null @@ -1,18 +0,0 @@ -AnyBlockchain in bdk::blockchain::any - Rust
pub enum AnyBlockchain {
-    Electrum(Box<ElectrumBlockchain>),
-    Esplora(Box<EsploraBlockchain>),
-    CompactFilters(Box<CompactFiltersBlockchain>),
-    Rpc(Box<RpcBlockchain>),
-}
Expand description

Type that can contain any of the Blockchain types defined by the library

-

It allows switching backend at runtime

-

See this module’s documentation for a usage example.

-

Variants§

§

Electrum(Box<ElectrumBlockchain>)

Available on crate feature electrum only.

Electrum client

-
§

Esplora(Box<EsploraBlockchain>)

Available on crate feature esplora only.

Esplora client

-
§

CompactFilters(Box<CompactFiltersBlockchain>)

Available on crate feature compact_filters only.

Compact filters client

-
§

Rpc(Box<RpcBlockchain>)

Available on crate feature rpc only.

RPC client

-

Trait Implementations§

Return the set of Capability supported by this backend
Broadcast a transaction
Estimate the fee rate required to confirm a transaction in a given target of blocks
Type that contains the configuration
Create a new instance given a configuration
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
fetch block hash given its height
Return the current height
Fetch a transaction given its txid
If not overridden, it defaults to calling Self::wallet_setup internally. Read more
Setup the backend and populate the internal database for the first time Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html deleted file mode 100644 index d13ac761a8..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html +++ /dev/null @@ -1,45 +0,0 @@ -AnyBlockchainConfig in bdk::blockchain::any - Rust
pub enum AnyBlockchainConfig {
-    Electrum(ElectrumBlockchainConfig),
-    Esplora(EsploraBlockchainConfig),
-    CompactFilters(CompactFiltersBlockchainConfig),
-    Rpc(RpcConfig),
-}
Expand description

Type that can contain any of the blockchain configurations defined by the library

-

This allows storing a single configuration that can be loaded into an AnyBlockchain -instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime -will find this particularly useful.

-

This type can be serialized from a JSON object like:

- -
use bdk::blockchain::{electrum::ElectrumBlockchainConfig, AnyBlockchainConfig};
-let config: AnyBlockchainConfig = serde_json::from_str(
-    r#"{
-   "type" : "electrum",
-   "url" : "ssl://electrum.blockstream.info:50002",
-   "retry": 2,
-   "stop_gap": 20,
-   "validate_domain": true
-}"#,
-)
-.unwrap();
-assert_eq!(
-    config,
-    AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig {
-        url: "ssl://electrum.blockstream.info:50002".into(),
-        retry: 2,
-        socks5: None,
-        timeout: None,
-        stop_gap: 20,
-        validate_domain: true,
-    })
-);
-

Variants§

§

Electrum(ElectrumBlockchainConfig)

Available on crate feature electrum only.

Electrum client

-
§

Esplora(EsploraBlockchainConfig)

Available on crate feature esplora only.

Esplora client

-
§

CompactFilters(CompactFiltersBlockchainConfig)

Available on crate feature compact_filters only.

Compact filters client

-
§

Rpc(RpcConfig)

Available on crate feature rpc only.

RPC client configuration

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/index.html deleted file mode 100644 index 766903a753..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/index.html +++ /dev/null @@ -1,12 +0,0 @@ -bdk::blockchain::any - Rust

Module bdk::blockchain::any

source ·
Expand description

Runtime-checked blockchain types

-

This module provides the implementation of AnyBlockchain which allows switching the -inner Blockchain type at runtime.

-

Example

-

When paired with the use of ConfigurableBlockchain, it allows creating any -blockchain type supported using a single line of code:

- -
let config = serde_json::from_str("...")?;
-let blockchain = AnyBlockchain::from_config(&config)?;
-let height = blockchain.get_height();
-

Enums

Type that can contain any of the Blockchain types defined by the library
Type that can contain any of the blockchain configurations defined by the library
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js deleted file mode 100644 index a478f31365..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["AnyBlockchain","Type that can contain any of the [`Blockchain`] types defined by the library"],["AnyBlockchainConfig","Type that can contain any of the blockchain configurations defined by the library"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html deleted file mode 100644 index ec834d3e9c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html +++ /dev/null @@ -1,41 +0,0 @@ -CompactFiltersError in bdk::blockchain::compact_filters - Rust
pub enum CompactFiltersError {
-
Show 16 variants InvalidResponse, - InvalidHeaders, - InvalidFilterHeader, - InvalidFilter, - MissingBlock, - BlockHashNotFound, - DataCorruption, - NotConnected, - Timeout, - PeerBloomDisabled, - NoPeers, - Db(Error), - Io(Error), - Bip158(Error), - Time(SystemTimeError), - Global(Box<Error>), -
}
Available on crate feature compact_filters only.
Expand description

An error that can occur during sync with a CompactFiltersBlockchain

-

Variants§

§

InvalidResponse

A peer sent an invalid or unexpected response

-
§

InvalidHeaders

The headers returned are invalid

-
§

InvalidFilterHeader

The compact filter headers returned are invalid

-
§

InvalidFilter

The compact filter returned is invalid

-
§

MissingBlock

The peer is missing a block in the valid chain

-
§

BlockHashNotFound

Block hash at specified height not found

-
§

DataCorruption

The data stored in the block filters storage are corrupted

-
§

NotConnected

A peer is not connected

-
§

Timeout

A peer took too long to reply to one of our messages

-
§

PeerBloomDisabled

The peer doesn’t advertise the BLOOM service flag

-
§

NoPeers

No peers have been specified

-
§

Db(Error)

Internal database error

-
§

Io(Error)

Internal I/O error

-
§

Bip158(Error)

Invalid BIP158 filter

-
§

Time(SystemTimeError)

Internal system time error

-
§

Global(Box<Error>)

Wrapper for crate::error::Error

-

Trait Implementations§

Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
The lower-level source of this error, if any. Read more
👎Deprecated since 1.42.0: use the Display impl or to_string()
👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
🔬This is a nightly-only experimental API. (provide_any)
Data providers should implement this method to provide all values they are able to -provide by using demand. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/index.html deleted file mode 100644 index 33ed7540f4..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/index.html +++ /dev/null @@ -1,28 +0,0 @@ -bdk::blockchain::compact_filters - Rust
Available on crate feature compact_filters only.
Expand description

Compact Filters

-

This module contains a multithreaded implementation of an Blockchain backend that -uses BIP157 (aka “Neutrino”) to populate the wallet’s database -by downloading compact filters from the P2P network.

-

Since there are currently very few peers “in the wild” that advertise the required service -flag, this implementation requires that one or more known peers are provided by the user. -No dns or other kinds of peer discovery are done internally.

-

Moreover, this module doesn’t currently support detecting and resolving conflicts between -messages received by different peers. Thus, it’s recommended to use this module by only -connecting to a single peer at a time, optionally by opening multiple connections if it’s -desirable to use multiple threads at once to sync in parallel.

-

This is an EXPERIMENTAL feature, API and other major changes are expected.

-

Example

-
let num_threads = 4;
-
-let mempool = Arc::new(Mempool::default());
-let peers = (0..num_threads)
-    .map(|_| {
-        Peer::connect(
-            "btcd-mainnet.lightning.computer:8333",
-            Arc::clone(&mempool),
-            Network::Bitcoin,
-        )
-    })
-    .collect::<Result<_, _>>()?;
-let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
-

Structs

Data to connect to a Bitcoin P2P peer
Structure implementing the required blockchain traits
Container for unconfirmed, but valid Bitcoin transactions
A Bitcoin peer

Enums

An error that can occur during sync with a CompactFiltersBlockchain
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/peer/struct.Mempool.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/peer/struct.Mempool.html deleted file mode 100644 index 744f72d99d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/peer/struct.Mempool.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../../../bdk/blockchain/compact_filters/struct.Mempool.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/peer/struct.Peer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/peer/struct.Peer.html deleted file mode 100644 index 4a3da2bc20..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/peer/struct.Peer.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../../../bdk/blockchain/compact_filters/struct.Peer.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js deleted file mode 100644 index 82f3cc2ddd..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["BitcoinPeerConfig","Data to connect to a Bitcoin P2P peer"],["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["CompactFiltersBlockchainConfig","Configuration for a [`CompactFiltersBlockchain`]"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html deleted file mode 100644 index c0778f9fc4..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html +++ /dev/null @@ -1,16 +0,0 @@ -BitcoinPeerConfig in bdk::blockchain::compact_filters - Rust
pub struct BitcoinPeerConfig {
-    pub address: String,
-    pub socks5: Option<String>,
-    pub socks5_credentials: Option<(String, String)>,
-}
Available on crate feature compact_filters only.
Expand description

Data to connect to a Bitcoin P2P peer

-

Fields§

§address: String

Peer address such as 127.0.0.1:18333

-
§socks5: Option<String>

Optional socks5 proxy

-
§socks5_credentials: Option<(String, String)>

Optional socks5 proxy credentials

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html deleted file mode 100644 index f74a9a0bc9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html +++ /dev/null @@ -1,16 +0,0 @@ -CompactFiltersBlockchain in bdk::blockchain::compact_filters - Rust
pub struct CompactFiltersBlockchain { /* private fields */ }
Available on crate feature compact_filters only.
Expand description

Structure implementing the required blockchain traits

-

Example

-

See the blockchain::compact_filters module for a usage example.

-

Implementations§

Construct a new instance given a list of peers, a path to store headers and block -filters downloaded during the sync and optionally a number of blocks to ignore starting -from the genesis while scanning for the wallet’s outputs.

-

For each Peer specified a new thread will be spawned to download and verify the filters -in parallel. It’s currently recommended to only connect to a single peer to avoid -inconsistencies in the data returned, optionally with multiple connections in parallel to -speed-up the sync process.

-

Trait Implementations§

Return the set of Capability supported by this backend
Broadcast a transaction
Estimate the fee rate required to confirm a transaction in a given target of blocks
Type that contains the configuration
Create a new instance given a configuration
Formats the value using the given formatter. Read more
Converts to this type from the input type.
fetch block hash given its height
Return the current height
Fetch a transaction given its txid
Setup the backend and populate the internal database for the first time Read more
If not overridden, it defaults to calling Self::wallet_setup internally. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html deleted file mode 100644 index e20e023b82..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html +++ /dev/null @@ -1,18 +0,0 @@ -CompactFiltersBlockchainConfig in bdk::blockchain::compact_filters - Rust
pub struct CompactFiltersBlockchainConfig {
-    pub peers: Vec<BitcoinPeerConfig>,
-    pub network: Network,
-    pub storage_dir: String,
-    pub skip_blocks: Option<usize>,
-}
Available on crate feature compact_filters only.
Expand description

Configuration for a CompactFiltersBlockchain

-

Fields§

§peers: Vec<BitcoinPeerConfig>

List of peers to try to connect to for asking headers and filters

-
§network: Network

Network used

-
§storage_dir: String

Storage dir to save partially downloaded headers and full blocks. Should be a separate directory per descriptor. Consider using crate::wallet::wallet_name_from_descriptor for this.

-
§skip_blocks: Option<usize>

Optionally skip initial skip_blocks blocks (default: 0)

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html deleted file mode 100644 index 1211d91519..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html +++ /dev/null @@ -1,16 +0,0 @@ -Mempool in bdk::blockchain::compact_filters - Rust
pub struct Mempool(_);
Available on crate feature compact_filters only.
Expand description

Container for unconfirmed, but valid Bitcoin transactions

-

It is normally shared between Peers with the use of Arc, so that transactions are not -duplicated in memory.

-

Implementations§

Create a new empty mempool

-

Add a transaction to the mempool

-

Note that this doesn’t propagate the transaction to other -peers. To do that, broadcast should be used.

-

Look-up a transaction in the mempool given an [Inventory] request

-

Return whether or not the mempool contains a transaction with a given txid

-

Return the list of transactions contained in the mempool

-

Trait Implementations§

Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html deleted file mode 100644 index 53e44a36f0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html +++ /dev/null @@ -1,20 +0,0 @@ -Peer in bdk::blockchain::compact_filters - Rust
pub struct Peer { /* private fields */ }
Available on crate feature compact_filters only.
Expand description

A Bitcoin peer

-

Implementations§

Connect to a peer over a plaintext TCP connection

-

This function internally spawns a new thread that will monitor incoming messages from the -peer, and optionally reply to some of them transparently, like pings

-

Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified -as a tuple of (username, password)

-

This function internally spawns a new thread that will monitor incoming messages from the -peer, and optionally reply to some of them transparently, like pings

-

Return the [VersionMessage] sent by the peer

-

Return the Bitcoin [Network] in use

-

Return the mempool used by this peer

-

Return whether or not the peer is still connected

-

Send a raw Bitcoin message to the peer

-

Waits for a specific incoming Bitcoin message, optionally with a timeout

-

Trait Implementations§

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/index.html deleted file mode 100644 index 25629826ce..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/index.html +++ /dev/null @@ -1,9 +0,0 @@ -bdk::blockchain::electrum - Rust

Module bdk::blockchain::electrum

source ·
Available on crate feature electrum only.
Expand description

Electrum

-

This module defines a Blockchain struct that wraps an [electrum_client::Client] -and implements the logic required to populate the wallet’s database by -querying the inner client.

-

Example

-
let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002")?;
-let blockchain = ElectrumBlockchain::from(client);
-

Structs

Wrapper over an Electrum Client that implements the required blockchain traits
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js deleted file mode 100644 index fc07f94fa7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"],["ElectrumBlockchainConfig","Configuration for an [`ElectrumBlockchain`]"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html deleted file mode 100644 index 172723104a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html +++ /dev/null @@ -1,9 +0,0 @@ -ElectrumBlockchain in bdk::blockchain::electrum - Rust
pub struct ElectrumBlockchain { /* private fields */ }
Available on crate feature electrum only.
Expand description

Wrapper over an Electrum Client that implements the required blockchain traits

-

Example

-

See the blockchain::electrum module for a usage example.

-

Trait Implementations§

Return the set of Capability supported by this backend
Broadcast a transaction
Estimate the fee rate required to confirm a transaction in a given target of blocks
Type that contains the configuration
Create a new instance given a configuration
The resulting type after dereferencing.
Dereferences the value.
Converts to this type from the input type.
Converts to this type from the input type.
fetch block hash given its height
Return the current height
Fetch a transaction given its txid
Setup the backend and populate the internal database for the first time Read more
If not overridden, it defaults to calling Self::wallet_setup internally. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html deleted file mode 100644 index a63acbffc2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html +++ /dev/null @@ -1,23 +0,0 @@ -ElectrumBlockchainConfig in bdk::blockchain::electrum - Rust
pub struct ElectrumBlockchainConfig {
-    pub url: String,
-    pub socks5: Option<String>,
-    pub retry: u8,
-    pub timeout: Option<u8>,
-    pub stop_gap: usize,
-    pub validate_domain: bool,
-}
Available on crate feature electrum only.
Expand description

Configuration for an ElectrumBlockchain

-

Fields§

§url: String

URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with ssl:// or tcp:// and include a port

-

eg. ssl://electrum.blockstream.info:60002

-
§socks5: Option<String>

URL of the socks5 proxy server or a Tor service

-
§retry: u8

Request retry count

-
§timeout: Option<u8>

Request timeout (seconds)

-
§stop_gap: usize

Stop searching addresses for transactions after finding an unused gap of this length

-
§validate_domain: bool

Validate the domain when using SSL

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/enum.Capability.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/enum.Capability.html deleted file mode 100644 index a4f01b8d6e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/enum.Capability.html +++ /dev/null @@ -1,16 +0,0 @@ -Capability in bdk::blockchain - Rust

Enum bdk::blockchain::Capability

source ·
pub enum Capability {
-    FullHistory,
-    GetAnyTx,
-    AccurateFees,
-}
Expand description

Capabilities that can be supported by a Blockchain backend

-

Variants§

§

FullHistory

Can recover the full history of a wallet and not only the set of currently spendable UTXOs

-
§

GetAnyTx

Can fetch any historical transaction given its txid

-
§

AccurateFees

Can compute accurate fees for the transactions found during sync

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/blocking/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/blocking/struct.EsploraBlockchain.html deleted file mode 100644 index 9e118ac7a5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/blocking/struct.EsploraBlockchain.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../../../bdk/blockchain/esplora/struct.EsploraBlockchain.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html deleted file mode 100644 index afb9117b1c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html +++ /dev/null @@ -1,31 +0,0 @@ -EsploraError in bdk::blockchain::esplora - Rust
pub enum EsploraError {
-    Ureq(Error),
-    UreqTransport(Transport),
-    HttpResponse(u16),
-    Io(Error),
-    NoHeader,
-    Parsing(ParseIntError),
-    BitcoinEncoding(Error),
-    Hex(Error),
-    TransactionNotFound(Txid),
-    HeaderHeightNotFound(u32),
-    HeaderHashNotFound(BlockHash),
-}
Available on crate feature esplora only.
Expand description

Errors that can happen during a sync with Esplora

-

Variants§

§

Ureq(Error)

Error during ureq HTTP request

-
§

UreqTransport(Transport)

Transport error during the ureq HTTP call

-
§

HttpResponse(u16)

HTTP response error

-
§

Io(Error)

IO error during ureq response read

-
§

NoHeader

No header found in ureq response

-
§

Parsing(ParseIntError)

Invalid number returned

-
§

BitcoinEncoding(Error)

Invalid Bitcoin data returned

-
§

Hex(Error)

Invalid Hex data returned

-
§

TransactionNotFound(Txid)

Transaction not found

-
§

HeaderHeightNotFound(u32)

Header height not found

-
§

HeaderHashNotFound(BlockHash)

Header hash not found

-

Trait Implementations§

Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
The lower-level source of this error, if any. Read more
👎Deprecated since 1.42.0: use the Display impl or to_string()
👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
🔬This is a nightly-only experimental API. (provide_any)
Data providers should implement this method to provide all values they are able to -provide by using demand. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/index.html deleted file mode 100644 index 71e42768bd..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/index.html +++ /dev/null @@ -1,12 +0,0 @@ -bdk::blockchain::esplora - Rust

Module bdk::blockchain::esplora

source ·
Available on crate feature esplora only.
Expand description

Esplora

-

This module defines a EsploraBlockchain struct that can query an Esplora -backend populate the wallet’s database by:

-

Example

-
let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", 20);
-

Esplora blockchain can use either ureq or reqwest for the HTTP client -depending on your needs (blocking or async respectively).

-

Please note, to configure the Esplora HTTP client correctly use one of: -Blocking: –features=‘use-esplora-blocking’ -Async: –features=‘async-interface,use-esplora-async’ –no-default-features

-

Structs

Structure that implements the logic to sync with Esplora

Enums

Errors that can happen during a sync with Esplora
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js deleted file mode 100644 index 387fca4052..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["EsploraError","Errors that can happen during a sync with `Esplora`"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["EsploraBlockchainConfig","Configuration for an [`EsploraBlockchain`]"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html deleted file mode 100644 index 3eb9494b34..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html +++ /dev/null @@ -1,37 +0,0 @@ -EsploraBlockchain in bdk::blockchain::esplora - Rust
pub struct EsploraBlockchain { /* private fields */ }
Available on crate feature esplora only.
Expand description

Structure that implements the logic to sync with Esplora

-

Example

-

See the blockchain::esplora module for a usage example.

-

Implementations§

Create a new instance of the client from a base URL and the stop_gap.

-

Build a new instance given a client

-

Set the number of parallel requests the client can make.

-

Methods from Deref<Target = BlockingClient>§

Get a [Transaction] option given its [Txid]

-

Get a [Transaction] given its [Txid].

-

Get a [Txid] of a transaction given its index in a block with a given hash.

-

Get the status of a [Transaction] given its [Txid].

-
👎Deprecated since 0.2.0: Deprecated to improve alignment with Esplora API. Users should use get_block_hash and get_header_by_hash methods directly.

Get a [BlockHeader] given a particular block height.

-

Get a [BlockHeader] given a particular block hash.

-

Get the [BlockStatus] given a particular [BlockHash].

-

Get a [Block] given a particular [BlockHash].

-

Get a merkle inclusion proof for a [Transaction] with the given [Txid].

-

Get a [MerkleBlock] inclusion proof for a [Transaction] with the given [Txid].

-

Get the spending status of an output given a [Txid] and the output index.

-

Broadcast a [Transaction] to Esplora

-

Get the height of the current blockchain tip.

-

Get the [BlockHash] of the current blockchain tip.

-

Get the [BlockHash] of a specific block height

-

Get an map where the key is the confirmation target (in number of blocks) -and the value is the estimated feerate (in sat/vB).

-

Get confirmed transaction history for the specified address/scripthash, -sorted with newest first. Returns 25 transactions per page. -More can be requested by specifying the last txid seen by the previous query.

-

Gets some recent block summaries starting at the tip or at height if provided.

-

The maximum number of summaries returned depends on the backend itself: esplora returns 10 -while mempool.space returns 15.

-

Get the underlying base URL.

-

Get the underlying [Agent].

-

Trait Implementations§

Return the set of Capability supported by this backend
Broadcast a transaction
Estimate the fee rate required to confirm a transaction in a given target of blocks
Type that contains the configuration
Create a new instance given a configuration
Formats the value using the given formatter. Read more
The resulting type after dereferencing.
Dereferences the value.
Converts to this type from the input type.
fetch block hash given its height
Return the current height
Fetch a transaction given its txid
Setup the backend and populate the internal database for the first time Read more
If not overridden, it defaults to calling Self::wallet_setup internally. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html deleted file mode 100644 index 95b120bc55..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html +++ /dev/null @@ -1,28 +0,0 @@ -EsploraBlockchainConfig in bdk::blockchain::esplora - Rust
pub struct EsploraBlockchainConfig {
-    pub base_url: String,
-    pub proxy: Option<String>,
-    pub concurrency: Option<u8>,
-    pub stop_gap: usize,
-    pub timeout: Option<u64>,
-}
Available on crate feature esplora only.
Expand description

Configuration for an EsploraBlockchain

-

Fields§

§base_url: String

Base URL of the esplora service

-

eg. https://blockstream.info/api/

-
§proxy: Option<String>

Optional URL of the proxy to use to make requests to the Esplora server

-

The string should be formatted as: <protocol>://<user>:<password>@host:<port>.

-

Note that the format of this value and the supported protocols change slightly between the -sync version of esplora (using ureq) and the async version (using reqwest). For more -details check with the documentation of the two crates. Both of them are compiled with -the socks feature enabled.

-

The proxy is ignored when targeting wasm32.

-
§concurrency: Option<u8>

Number of parallel requests sent to the esplora service (default: 4)

-
§stop_gap: usize

Stop searching addresses for transactions after finding an unused gap of this length.

-
§timeout: Option<u64>

Socket timeout.

-

Implementations§

create a config with default values given the base url and stop gap

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.log_progress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.log_progress.html deleted file mode 100644 index c16cc8739c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.log_progress.html +++ /dev/null @@ -1,3 +0,0 @@ -log_progress in bdk::blockchain - Rust

Function bdk::blockchain::log_progress

source ·
pub fn log_progress() -> LogProgress
Expand description

Create a new instance of LogProgress

-
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.noop_progress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.noop_progress.html deleted file mode 100644 index ae7fad3d95..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.noop_progress.html +++ /dev/null @@ -1,3 +0,0 @@ -noop_progress in bdk::blockchain - Rust

Function bdk::blockchain::noop_progress

source ·
pub fn noop_progress() -> NoopProgress
Expand description

Create a new instance of NoopProgress

-
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.progress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.progress.html deleted file mode 100644 index ff7ce67246..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.progress.html +++ /dev/null @@ -1,3 +0,0 @@ -progress in bdk::blockchain - Rust

Function bdk::blockchain::progress

source ·
pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)
Expand description

Shortcut to create a channel (pair of Sender and Receiver) that can transport ProgressData

-
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/index.html deleted file mode 100644 index 1639cb92c4..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/index.html +++ /dev/null @@ -1,8 +0,0 @@ -bdk::blockchain - Rust

Module bdk::blockchain

source ·
Expand description

Blockchain backends

-

This module provides the implementation of a few commonly-used backends like -Electrum, Esplora and -Compact Filters/Neutrino, along with a generalized trait -Blockchain that can be implemented to build customized backends.

-

Re-exports

pub use any::AnyBlockchain;
pub use any::AnyBlockchainConfig;
pub use self::electrum::ElectrumBlockchain;
pub use self::electrum::ElectrumBlockchainConfig;
pub use self::rpc::RpcBlockchain;
pub use self::rpc::RpcConfig;
pub use self::compact_filters::CompactFiltersBlockchain;

Modules

Runtime-checked blockchain types
compact_filterscompact_filters
Compact Filters
electrumelectrum
Electrum
esploraesplora
Esplora
rpcrpc
Rpc Blockchain

Structs

Structure that implements the logic to sync with Esplora
Type that implements Progress and logs at level INFO every update received
Type that implements Progress and drops every update received

Enums

Capabilities that can be supported by a Blockchain backend

Traits

Trait that defines the actions that must be supported by a blockchain backend
Trait for a factory of blockchains that share the underlying connection or configuration
Trait for Blockchain types that can be created given a configuration
Trait for getting block hash by block height
Trait for getting the current height of the blockchain.
Trait for getting a transaction by txid
Trait for types that can receive and process progress updates during WalletSync::wallet_sync and -WalletSync::wallet_setup
Trait for blockchains that don’t contain any state
Trait for blockchains that can sync by updating the database directly.

Functions

Create a new instance of LogProgress
Create a new instance of NoopProgress
Shortcut to create a channel (pair of Sender and Receiver) that can transport ProgressData

Type Definitions

Data sent with a progress update over a channel
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/enum.Auth.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/enum.Auth.html deleted file mode 100644 index 27fd38c656..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/enum.Auth.html +++ /dev/null @@ -1,28 +0,0 @@ -Auth in bdk::blockchain::rpc - Rust

Enum bdk::blockchain::rpc::Auth

source ·
pub enum Auth {
-    None,
-    UserPass {
-        username: String,
-        password: String,
-    },
-    Cookie {
-        file: PathBuf,
-    },
-}
Available on crate feature rpc only.
Expand description

This struct is equivalent to [bitcoincore_rpc::Auth] but it implements serde::Serialize -To be removed once upstream equivalent is implementing Serialize (json serialization format -should be the same), see rust-bitcoincore-rpc/pull/181

-

Variants§

§

None

None authentication

-
§

UserPass

Fields

§username: String

Username

-
§password: String

Password

-

Authentication with username and password, usually Auth::Cookie should be preferred

-
§

Cookie

Fields

§file: PathBuf

Cookie file

-

Authentication with a cookie file

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= -operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/index.html deleted file mode 100644 index 9f14791756..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/index.html +++ /dev/null @@ -1,18 +0,0 @@ -bdk::blockchain::rpc - Rust

Module bdk::blockchain::rpc

source ·
Available on crate feature rpc only.
Expand description

Rpc Blockchain

-

Backend that gets blockchain data from Bitcoin Core RPC

-

This is an EXPERIMENTAL feature, API and other major changes are expected.

-

Example

-
let config = RpcConfig {
-    url: "127.0.0.1:18332".to_string(),
-    auth: Auth::Cookie {
-        file: "/home/user/.bitcoin/.cookie".into(),
-    },
-    network: bdk::bitcoin::Network::Testnet,
-    wallet_name: "wallet_name".to_string(),
-    sync_params: None,
-};
-let blockchain = RpcBlockchain::from_config(&config);
-

Structs

The main struct for RPC backend implementing the crate::blockchain::Blockchain trait
Factory of RpcBlockchain instances, implements BlockchainFactory
RpcBlockchain configuration options
Sync parameters for Bitcoin Core RPC.

Enums

This struct is equivalent to [bitcoincore_rpc::Auth] but it implements serde::Serialize -To be removed once upstream equivalent is implementing Serialize (json serialization format -should be the same), see rust-bitcoincore-rpc/pull/181
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/sidebar-items.js deleted file mode 100644 index 8e01f942a8..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["Auth","This struct is equivalent to [bitcoincore_rpc::Auth] but it implements [serde::Serialize] To be removed once upstream equivalent is implementing Serialize (json serialization format should be the same), see rust-bitcoincore-rpc/pull/181"]],"struct":[["RpcBlockchain","The main struct for RPC backend implementing the [crate::blockchain::Blockchain] trait"],["RpcBlockchainFactory","Factory of [`RpcBlockchain`] instances, implements [`BlockchainFactory`]"],["RpcConfig","RpcBlockchain configuration options"],["RpcSyncParams","Sync parameters for Bitcoin Core RPC."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcBlockchain.html deleted file mode 100644 index 098bc44175..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcBlockchain.html +++ /dev/null @@ -1,10 +0,0 @@ -RpcBlockchain in bdk::blockchain::rpc - Rust

Struct bdk::blockchain::rpc::RpcBlockchain

source ·
pub struct RpcBlockchain { /* private fields */ }
Available on crate feature rpc only.
Expand description

The main struct for RPC backend implementing the crate::blockchain::Blockchain trait

-

Methods from Deref<Target = Client>§

Get the underlying JSONRPC client.

-

Trait Implementations§

Return the set of Capability supported by this backend
Broadcast a transaction
Estimate the fee rate required to confirm a transaction in a given target of blocks

Returns RpcBlockchain backend creating an RPC client to a specific wallet named as the descriptor’s checksum -if it’s the first time it creates the wallet in the node and upon return is granted the wallet is loaded

-
Type that contains the configuration
Formats the value using the given formatter. Read more
The resulting type after dereferencing.
Dereferences the value.
Converts to this type from the input type.
fetch block hash given its height
Return the current height
Fetch a transaction given its txid
Setup the backend and populate the internal database for the first time Read more
If not overridden, it defaults to calling Self::wallet_setup internally. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcBlockchainFactory.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcBlockchainFactory.html deleted file mode 100644 index 6b12a58b39..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcBlockchainFactory.html +++ /dev/null @@ -1,34 +0,0 @@ -RpcBlockchainFactory in bdk::blockchain::rpc - Rust
pub struct RpcBlockchainFactory {
-    pub url: String,
-    pub auth: Auth,
-    pub network: Network,
-    pub wallet_name_prefix: Option<String>,
-    pub default_skip_blocks: u32,
-    pub sync_params: Option<RpcSyncParams>,
-}
Available on crate feature rpc only.
Expand description

Factory of RpcBlockchain instances, implements BlockchainFactory

-

Internally caches the node url and authentication params and allows getting many different RpcBlockchain -objects for different wallet names and with different rescan heights.

-

Example

-
let factory = RpcBlockchainFactory {
-    url: "http://127.0.0.1:18332".to_string(),
-    auth: Auth::Cookie {
-        file: "/home/user/.bitcoin/.cookie".into(),
-    },
-    network: Network::Testnet,
-    wallet_name_prefix: Some("prefix-".to_string()),
-    default_skip_blocks: 100_000,
-    sync_params: None,
-};
-let main_wallet_blockchain = factory.build("main_wallet", Some(200_000))?;
-

Fields§

§url: String

The bitcoin node url

-
§auth: Auth

The bitcoin node authentication mechanism

-
§network: Network

The network we are using (it will be checked the bitcoin node network matches this)

-
§wallet_name_prefix: Option<String>

The optional prefix used to build the full wallet name for blockchains

-
§default_skip_blocks: u32

Default number of blocks to skip which will be inherited by blockchain unless overridden

-
§sync_params: Option<RpcSyncParams>

Sync parameters

-

Trait Implementations§

The type returned when building a blockchain from this factory
Build a new blockchain for the given descriptor wallet_name Read more
Build a new blockchain for a given wallet Read more
Available on non-crate feature async-interface only.
Use BlockchainFactory::build_for_wallet to get a blockchain, then sync the wallet Read more
Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcConfig.html deleted file mode 100644 index 6c6b6527fb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcConfig.html +++ /dev/null @@ -1,20 +0,0 @@ -RpcConfig in bdk::blockchain::rpc - Rust

Struct bdk::blockchain::rpc::RpcConfig

source ·
pub struct RpcConfig {
-    pub url: String,
-    pub auth: Auth,
-    pub network: Network,
-    pub wallet_name: String,
-    pub sync_params: Option<RpcSyncParams>,
-}
Available on crate feature rpc only.
Expand description

RpcBlockchain configuration options

-

Fields§

§url: String

The bitcoin node url

-
§auth: Auth

The bitcoin node authentication mechanism

-
§network: Network

The network we are using (it will be checked the bitcoin node network matches this)

-
§wallet_name: String

The wallet name in the bitcoin node, consider using crate::wallet::wallet_name_from_descriptor for this

-
§sync_params: Option<RpcSyncParams>

Sync parameters

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcSyncParams.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcSyncParams.html deleted file mode 100644 index 205fbfecf1..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/rpc/struct.RpcSyncParams.html +++ /dev/null @@ -1,21 +0,0 @@ -RpcSyncParams in bdk::blockchain::rpc - Rust

Struct bdk::blockchain::rpc::RpcSyncParams

source ·
pub struct RpcSyncParams {
-    pub start_script_count: usize,
-    pub start_time: u64,
-    pub force_start_time: bool,
-    pub poll_rate_sec: u64,
-}
Available on crate feature rpc only.
Expand description

Sync parameters for Bitcoin Core RPC.

-

In general, BDK tries to sync scriptPubKeys cached in crate::database::Database with -scriptPubKeys imported in the Bitcoin Core Wallet. These parameters are used for determining -how the importdescriptors RPC calls are to be made.

-

Fields§

§start_script_count: usize

The minimum number of scripts to scan for on initial sync.

-
§start_time: u64

Time in unix seconds in which initial sync will start scanning from (0 to start from genesis).

-
§force_start_time: bool

Forces every sync to use start_time as import timestamp.

-
§poll_rate_sec: u64

RPC poll rate (in seconds) to get state updates.

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Deserialize this value from the given Serde deserializer. Read more
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js deleted file mode 100644 index 50df514818..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a new instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["any","Runtime-checked blockchain types"],["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"],["rpc","Rpc Blockchain"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["BlockchainFactory","Trait for a factory of blockchains that share the underlying connection or configuration"],["ConfigurableBlockchain","Trait for [`Blockchain`] types that can be created given a configuration"],["GetBlockHash","Trait for getting block hash by block height"],["GetHeight","Trait for getting the current height of the blockchain."],["GetTx","Trait for getting a transaction by txid"],["Progress","Trait for types that can receive and process progress updates during [`WalletSync::wallet_sync`] and [`WalletSync::wallet_setup`]"],["StatelessBlockchain","Trait for blockchains that don’t contain any state"],["WalletSync","Trait for blockchains that can sync by updating the database directly."]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html deleted file mode 100644 index 5858c63d4c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html +++ /dev/null @@ -1,37 +0,0 @@ -EsploraBlockchain in bdk::blockchain - Rust
pub struct EsploraBlockchain { /* private fields */ }
Available on crate feature esplora only.
Expand description

Structure that implements the logic to sync with Esplora

-

Example

-

See the blockchain::esplora module for a usage example.

-

Implementations§

Create a new instance of the client from a base URL and the stop_gap.

-

Build a new instance given a client

-

Set the number of parallel requests the client can make.

-

Methods from Deref<Target = BlockingClient>§

Get a [Transaction] option given its [Txid]

-

Get a [Transaction] given its [Txid].

-

Get a [Txid] of a transaction given its index in a block with a given hash.

-

Get the status of a [Transaction] given its [Txid].

-
👎Deprecated since 0.2.0: Deprecated to improve alignment with Esplora API. Users should use get_block_hash and get_header_by_hash methods directly.

Get a [BlockHeader] given a particular block height.

-

Get a [BlockHeader] given a particular block hash.

-

Get the [BlockStatus] given a particular [BlockHash].

-

Get a [Block] given a particular [BlockHash].

-

Get a merkle inclusion proof for a [Transaction] with the given [Txid].

-

Get a [MerkleBlock] inclusion proof for a [Transaction] with the given [Txid].

-

Get the spending status of an output given a [Txid] and the output index.

-

Broadcast a [Transaction] to Esplora

-

Get the height of the current blockchain tip.

-

Get the [BlockHash] of the current blockchain tip.

-

Get the [BlockHash] of a specific block height

-

Get an map where the key is the confirmation target (in number of blocks) -and the value is the estimated feerate (in sat/vB).

-

Get confirmed transaction history for the specified address/scripthash, -sorted with newest first. Returns 25 transactions per page. -More can be requested by specifying the last txid seen by the previous query.

-

Gets some recent block summaries starting at the tip or at height if provided.

-

The maximum number of summaries returned depends on the backend itself: esplora returns 10 -while mempool.space returns 15.

-

Get the underlying base URL.

-

Get the underlying [Agent].

-

Trait Implementations§

Return the set of Capability supported by this backend
Broadcast a transaction
Estimate the fee rate required to confirm a transaction in a given target of blocks
Type that contains the configuration
Create a new instance given a configuration
Formats the value using the given formatter. Read more
The resulting type after dereferencing.
Dereferences the value.
Converts to this type from the input type.
fetch block hash given its height
Return the current height
Fetch a transaction given its txid
Setup the backend and populate the internal database for the first time Read more
If not overridden, it defaults to calling Self::wallet_setup internally. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html deleted file mode 100644 index 997b7e3288..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html +++ /dev/null @@ -1,7 +0,0 @@ -LogProgress in bdk::blockchain - Rust

Struct bdk::blockchain::LogProgress

source ·
pub struct LogProgress;
Expand description

Type that implements Progress and logs at level INFO every update received

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Send a new progress update Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.NoopProgress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.NoopProgress.html deleted file mode 100644 index d342a9e7ce..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.NoopProgress.html +++ /dev/null @@ -1,7 +0,0 @@ -NoopProgress in bdk::blockchain - Rust

Struct bdk::blockchain::NoopProgress

source ·
pub struct NoopProgress;
Expand description

Type that implements Progress and drops every update received

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Send a new progress update Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Blockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Blockchain.html deleted file mode 100644 index 5cc0c174e0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Blockchain.html +++ /dev/null @@ -1,10 +0,0 @@ -Blockchain in bdk::blockchain - Rust

Trait bdk::blockchain::Blockchain

source ·
pub trait Blockchain: WalletSync + GetHeight + GetTx + GetBlockHash {
-    fn get_capabilities(&self) -> HashSet<Capability>;
-    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
-    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
-}
Expand description

Trait that defines the actions that must be supported by a blockchain backend

-

Required Methods§

Return the set of Capability supported by this backend

-

Broadcast a transaction

-

Estimate the fee rate required to confirm a transaction in a given target of blocks

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.BlockchainFactory.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.BlockchainFactory.html deleted file mode 100644 index f635723cd7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.BlockchainFactory.html +++ /dev/null @@ -1,38 +0,0 @@ -BlockchainFactory in bdk::blockchain - Rust
pub trait BlockchainFactory {
-    type Inner: Blockchain;
-
-    fn build(
        &self,
        wallet_name: &str,
        override_skip_blocks: Option<u32>
    ) -> Result<Self::Inner, Error>; - - fn build_for_wallet<D: BatchDatabase>(
        &self,
        wallet: &Wallet<D>,
        override_skip_blocks: Option<u32>
    ) -> Result<Self::Inner, Error> { ... } - fn sync_wallet<D: BatchDatabase>(
        &self,
        wallet: &Wallet<D>,
        override_skip_blocks: Option<u32>,
        sync_options: SyncOptions
    ) -> Result<(), Error> { ... } -}
Expand description

Trait for a factory of blockchains that share the underlying connection or configuration

-

Example

-

This example shows how to sync multiple walles and return the sum of their balances

- -
fn sum_of_balances<B: BlockchainFactory>(blockchain_factory: B, wallets: &[Wallet<MemoryDatabase>]) -> Result<Balance, Error> {
-    Ok(wallets
-        .iter()
-        .map(|w| -> Result<_, Error> {
-            blockchain_factory.sync_wallet(&w, None, SyncOptions::default())?;
-            w.get_balance()
-        })
-        .collect::<Result<Vec<_>, _>>()?
-        .into_iter()
-        .sum())
-}
-

Required Associated Types§

The type returned when building a blockchain from this factory

-

Required Methods§

Build a new blockchain for the given descriptor wallet_name

-

If override_skip_blocks is None, the returned blockchain will inherit the number of blocks -from the factory. Since it’s not possible to override the value to None, set it to -Some(0) to rescan from the genesis.

-

Provided Methods§

Build a new blockchain for a given wallet

-

Internally uses wallet_name_from_descriptor to derive the name, and then calls -BlockchainFactory::build to create the blockchain instance.

-
Available on non-crate feature async-interface only.

Use BlockchainFactory::build_for_wallet to get a blockchain, then sync the wallet

-

This can be used when a new blockchain would only be used to sync a wallet and then -immediately dropped. Keep in mind that specific blockchain factories may perform slow -operations to build a blockchain for a given wallet, so if a wallet needs to be synced -often it’s recommended to use BlockchainFactory::build_for_wallet to reuse the same -blockchain multiple times.

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.ConfigurableBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.ConfigurableBlockchain.html deleted file mode 100644 index 39c301204d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.ConfigurableBlockchain.html +++ /dev/null @@ -1,9 +0,0 @@ -ConfigurableBlockchain in bdk::blockchain - Rust
pub trait ConfigurableBlockchain: Blockchain + Sized {
-    type Config: Debug;
-
-    fn from_config(config: &Self::Config) -> Result<Self, Error>;
-}
Expand description

Trait for Blockchain types that can be created given a configuration

-

Required Associated Types§

Type that contains the configuration

-

Required Methods§

Create a new instance given a configuration

-

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetBlockHash.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetBlockHash.html deleted file mode 100644 index 46534717d5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetBlockHash.html +++ /dev/null @@ -1,6 +0,0 @@ -GetBlockHash in bdk::blockchain - Rust

Trait bdk::blockchain::GetBlockHash

source ·
pub trait GetBlockHash {
-    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error>;
-}
Expand description

Trait for getting block hash by block height

-

Required Methods§

fetch block hash given its height

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetHeight.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetHeight.html deleted file mode 100644 index bd109ade1b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetHeight.html +++ /dev/null @@ -1,6 +0,0 @@ -GetHeight in bdk::blockchain - Rust

Trait bdk::blockchain::GetHeight

source ·
pub trait GetHeight {
-    fn get_height(&self) -> Result<u32, Error>;
-}
Expand description

Trait for getting the current height of the blockchain.

-

Required Methods§

Return the current height

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetTx.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetTx.html deleted file mode 100644 index 0670c0815c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.GetTx.html +++ /dev/null @@ -1,6 +0,0 @@ -GetTx in bdk::blockchain - Rust

Trait bdk::blockchain::GetTx

source ·
pub trait GetTx {
-    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
-}
Expand description

Trait for getting a transaction by txid

-

Required Methods§

Fetch a transaction given its txid

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Progress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Progress.html deleted file mode 100644 index 29888cf2c7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Progress.html +++ /dev/null @@ -1,9 +0,0 @@ -Progress in bdk::blockchain - Rust

Trait bdk::blockchain::Progress

source ·
pub trait Progress: Send + 'static + Debug {
-    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
-}
Expand description

Trait for types that can receive and process progress updates during WalletSync::wallet_sync and -WalletSync::wallet_setup

-

Required Methods§

Send a new progress update

-

The progress value should be in the range 0.0 - 100.0, and the message value is an -optional text message that can be displayed to the user.

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.StatelessBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.StatelessBlockchain.html deleted file mode 100644 index f4cafe1219..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.StatelessBlockchain.html +++ /dev/null @@ -1,6 +0,0 @@ -StatelessBlockchain in bdk::blockchain - Rust
pub trait StatelessBlockchain: Blockchain { }
Expand description

Trait for blockchains that don’t contain any state

-

Statless blockchains can be used to sync multiple wallets with different descriptors.

-

BlockchainFactory is automatically implemented for Arc<T> where T is a stateless -blockchain.

-

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.WalletSync.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.WalletSync.html deleted file mode 100644 index c51af40484..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.WalletSync.html +++ /dev/null @@ -1,24 +0,0 @@ -WalletSync in bdk::blockchain - Rust

Trait bdk::blockchain::WalletSync

source ·
pub trait WalletSync {
-    fn wallet_setup<D: BatchDatabase>(
        &self,
        database: &RefCell<D>,
        progress_update: Box<dyn Progress>
    ) -> Result<(), Error>; - - fn wallet_sync<D: BatchDatabase>(
        &self,
        database: &RefCell<D>,
        progress_update: Box<dyn Progress>
    ) -> Result<(), Error> { ... } -}
Expand description

Trait for blockchains that can sync by updating the database directly.

-

Required Methods§

Setup the backend and populate the internal database for the first time

-

This method is the equivalent of Self::wallet_sync, but it’s guaranteed to only be -called once, at the first Wallet::sync.

-

The rationale behind the distinction between sync and setup is that some custom backends -might need to perform specific actions only the first time they are synced.

-

For types that do not have that distinction, only this method can be implemented, since -WalletSync::wallet_sync defaults to calling this internally if not overridden. -Populate the internal database with transactions and UTXOs

-

Provided Methods§

If not overridden, it defaults to calling Self::wallet_setup internally.

-

This method should implement the logic required to iterate over the list of the wallet’s -script_pubkeys using Database::iter_script_pubkeys and look for relevant transactions -in the blockchain to populate the database with BatchOperations::set_tx and -BatchOperations::set_utxo.

-

This method should also take care of removing UTXOs that are seen as spent in the -blockchain, using BatchOperations::del_utxo.

-

The progress_update object can be used to give the caller updates about the progress by using -Progress::update.

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/type.ProgressData.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/type.ProgressData.html deleted file mode 100644 index fd377c48da..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/type.ProgressData.html +++ /dev/null @@ -1,3 +0,0 @@ -ProgressData in bdk::blockchain - Rust

Type Definition bdk::blockchain::ProgressData

source ·
pub type ProgressData = (f32, Option<String>);
Expand description

Data sent with a progress update over a channel

-
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyBatch.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyBatch.html deleted file mode 100644 index c71e8870d2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyBatch.html +++ /dev/null @@ -1,15 +0,0 @@ -AnyBatch in bdk::database::any - Rust

Enum bdk::database::any::AnyBatch

source ·
pub enum AnyBatch {
-    Memory(<MemoryDatabase as BatchDatabase>::Batch),
-    Sled(<Tree as BatchDatabase>::Batch),
-    Sqlite(<SqliteDatabase as BatchDatabase>::Batch),
-}
Expand description

Type that contains any of the BatchDatabase::Batch types defined by the library

-

Variants§

§

Memory(<MemoryDatabase as BatchDatabase>::Batch)

In-memory ephemeral database

-
§

Sled(<Tree as BatchDatabase>::Batch)

Available on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

-
§

Sqlite(<SqliteDatabase as BatchDatabase>::Batch)

Available on crate feature sqlite only.

Sqlite embedded database using [rusqlite]

-

Trait Implementations§

Store a script_pubkey along with its keychain and child number.
Store a LocalUtxo
Store a raw transaction
Store the metadata of a transaction
Store the last derivation index for a given keychain.
Store the sync time
Delete a script_pubkey given the keychain and its child number.
Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more
Delete a LocalUtxo given its [OutPoint]
Delete a raw transaction given its [Txid]
Delete the metadata of a transaction and optionally the raw transaction itself
Delete the last derivation index for a keychain.
Reset the sync time to None Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabase.html deleted file mode 100644 index e63e401b80..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabase.html +++ /dev/null @@ -1,17 +0,0 @@ -AnyDatabase in bdk::database::any - Rust

Enum bdk::database::any::AnyDatabase

source ·
pub enum AnyDatabase {
-    Memory(MemoryDatabase),
-    Sled(Tree),
-    Sqlite(SqliteDatabase),
-}
Expand description

Type that can contain any of the Database types defined by the library

-

It allows switching database type at runtime.

-

See this module’s documentation for a usage example.

-

Variants§

§

Memory(MemoryDatabase)

In-memory ephemeral database

-
§

Sled(Tree)

Available on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

-
§

Sqlite(SqliteDatabase)

Available on crate feature sqlite only.

Sqlite embedded database using [rusqlite]

-

Trait Implementations§

Container for the operations
Create a new batch container
Consume and apply a batch of operations
Store a script_pubkey along with its keychain and child number.
Store a LocalUtxo
Store a raw transaction
Store the metadata of a transaction
Store the last derivation index for a given keychain.
Store the sync time
Delete a script_pubkey given the keychain and its child number.
Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more
Delete a LocalUtxo given its [OutPoint]
Delete a raw transaction given its [Txid]
Delete the metadata of a transaction and optionally the raw transaction itself
Delete the last derivation index for a keychain.
Reset the sync time to None Read more
Type that contains the configuration
Create a new instance given a configuration
Read and checks the descriptor checksum for a given keychain. Read more
Return the list of script_pubkeys
Return the list of LocalUtxos
Return the list of raw transactions
Return the list of transactions metadata
Fetch a script_pubkey given the child number of a keychain.
Fetch the keychain and child number of a given script_pubkey
Fetch a LocalUtxo given its [OutPoint]
Fetch a raw transaction given its [Txid]
Fetch the transaction metadata and optionally also the raw transaction
Return the last derivation index for a keychain.
Return the sync time, if present
Increment the last derivation index for a keychain and return it Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabaseConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabaseConfig.html deleted file mode 100644 index 5bc6b7c2ad..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabaseConfig.html +++ /dev/null @@ -1,17 +0,0 @@ -AnyDatabaseConfig in bdk::database::any - Rust
pub enum AnyDatabaseConfig {
-    Memory(()),
-    Sled(SledDbConfiguration),
-    Sqlite(SqliteDbConfiguration),
-}
Expand description

Type that can contain any of the database configurations defined by the library

-

This allows storing a single configuration that can be loaded into an AnyDatabase -instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime -will find this particularly useful.

-

Variants§

§

Memory(())

Memory database has no config

-
§

Sled(SledDbConfiguration)

Available on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

-
§

Sqlite(SqliteDbConfiguration)

Available on crate feature sqlite only.

Sqlite embedded database using [rusqlite]

-

Trait Implementations§

Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/index.html deleted file mode 100644 index 3c9075e0c2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/index.html +++ /dev/null @@ -1,19 +0,0 @@ -bdk::database::any - Rust

Module bdk::database::any

source ·
Expand description

Runtime-checked database types

-

This module provides the implementation of AnyDatabase which allows switching the -inner Database type at runtime.

-

Example

-

In this example, wallet_memory and wallet_sled have the same type of Wallet<(), AnyDatabase>.

- -
let memory = MemoryDatabase::default();
-let wallet_memory = Wallet::new("...", None, Network::Testnet, memory)?;
-
-let sled = sled::open("my-database")?.open_tree("default_tree")?;
-let wallet_sled = Wallet::new("...", None, Network::Testnet, sled)?;
-

When paired with the use of ConfigurableDatabase, it allows creating wallets with any -database supported using a single line of code:

- -
let config = serde_json::from_str("...")?;
-let database = AnyDatabase::from_config(&config)?;
-let wallet = Wallet::new("...", None, Network::Testnet, database)?;
-

Structs

Configuration type for a [sled::Tree] database
Configuration type for a sqlite::SqliteDatabase database

Enums

Type that contains any of the BatchDatabase::Batch types defined by the library
Type that can contain any of the Database types defined by the library
Type that can contain any of the database configurations defined by the library
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js deleted file mode 100644 index 42ce79a41c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["AnyBatch","Type that contains any of the [`BatchDatabase::Batch`] types defined by the library"],["AnyDatabase","Type that can contain any of the [`Database`] types defined by the library"],["AnyDatabaseConfig","Type that can contain any of the database configurations defined by the library"]],"struct":[["SledDbConfiguration","Configuration type for a [`sled::Tree`] database"],["SqliteDbConfiguration","Configuration type for a [`sqlite::SqliteDatabase`] database"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html deleted file mode 100644 index 372a65fe50..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html +++ /dev/null @@ -1,12 +0,0 @@ -SledDbConfiguration in bdk::database::any - Rust
pub struct SledDbConfiguration {
-    pub path: String,
-    pub tree_name: String,
-}
Expand description

Configuration type for a [sled::Tree] database

-

Fields§

§path: String

Main directory of the db

-
§tree_name: String

Name of the database tree, a separated namespace for the data

-

Trait Implementations§

Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html deleted file mode 100644 index f74dcd32f7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html +++ /dev/null @@ -1,10 +0,0 @@ -SqliteDbConfiguration in bdk::database::any - Rust
pub struct SqliteDbConfiguration {
-    pub path: String,
-}
Expand description

Configuration type for a sqlite::SqliteDatabase database

-

Fields§

§path: String

Main directory of the db

-

Trait Implementations§

Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/index.html deleted file mode 100644 index 960b59f15f..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/index.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::database - Rust

Module bdk::database

source ·
Expand description

Database types

-

This module provides the implementation of some defaults database types, along with traits that -can be implemented externally to let Wallets use customized databases.

-

It’s important to note that the databases defined here only contains “blockchain-related” data. -They can be seen more as a cache than a critical piece of storage that contains secrets and -keys.

-

The currently recommended database is [sled], which is a pretty simple key-value embedded -database written in Rust. If the key-value-db feature is enabled (which by default is), -this library automatically implements all the required traits for [sled::Tree].

-

Re-exports

pub use any::AnyDatabase;
pub use any::AnyDatabaseConfig;
pub use memory::MemoryDatabase;

Modules

Runtime-checked database types
In-memory ephemeral database

Structs

Sqlite database stored on filesystem
Blockchain state at the time of syncing

Traits

Trait for a database that supports batch operations
Trait for operations that can be batched
Trait for Database types that can be created given a configuration
Trait for reading data from a database
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/index.html deleted file mode 100644 index 00b9074d82..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/index.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::database::memory - Rust

Module bdk::database::memory

source ·
Expand description

In-memory ephemeral database

-

This module defines an in-memory database type called MemoryDatabase that is based on a -BTreeMap.

-

Structs

In-memory ephemeral database
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js deleted file mode 100644 index 3275d45f7d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"struct":[["MemoryDatabase","In-memory ephemeral database"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html deleted file mode 100644 index b08fa1faec..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html +++ /dev/null @@ -1,14 +0,0 @@ -MemoryDatabase in bdk::database::memory - Rust
pub struct MemoryDatabase { /* private fields */ }
Expand description

In-memory ephemeral database

-

This database can be used as a temporary storage for wallets that are not kept permanently on -a device, or on platforms that don’t provide a filesystem, like wasm32.

-

Once it’s dropped its content will be lost.

-

If you are looking for a permanent storage solution, you can try with the default key-value -database called [sled]. See the database module documentation for more details.

-

Implementations§

Create a new empty database

-

Trait Implementations§

Container for the operations
Create a new batch container
Consume and apply a batch of operations
Store a script_pubkey along with its keychain and child number.
Store a LocalUtxo
Store a raw transaction
Store the metadata of a transaction
Store the last derivation index for a given keychain.
Store the sync time
Delete a script_pubkey given the keychain and its child number.
Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more
Delete a LocalUtxo given its [OutPoint]
Delete a raw transaction given its [Txid]
Delete the metadata of a transaction and optionally the raw transaction itself
Delete the last derivation index for a keychain.
Reset the sync time to None Read more
Type that contains the configuration
Create a new instance given a configuration
Read and checks the descriptor checksum for a given keychain. Read more
Return the list of script_pubkeys
Return the list of LocalUtxos
Return the list of raw transactions
Return the list of transactions metadata
Fetch a script_pubkey given the child number of a keychain.
Fetch the keychain and child number of a given script_pubkey
Fetch a LocalUtxo given its [OutPoint]
Fetch a raw transaction given its [Txid]
Fetch the transaction metadata and optionally also the raw transaction
Return the last derivation index for a keychain.
Return the sync time, if present
Increment the last derivation index for a keychain and return it Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js deleted file mode 100644 index 1675cea1c4..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"mod":[["any","Runtime-checked database types"],["memory","In-memory ephemeral database"]],"struct":[["SqliteDatabase","Sqlite database stored on filesystem"],["SyncTime","Blockchain state at the time of syncing"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["ConfigurableDatabase","Trait for [`Database`] types that can be created given a configuration"],["Database","Trait for reading data from a database"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html deleted file mode 100644 index 803ba38ba6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../../bdk/database/struct.SqliteDatabase.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/struct.SqliteDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/struct.SqliteDatabase.html deleted file mode 100644 index a15cf92209..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/struct.SqliteDatabase.html +++ /dev/null @@ -1,17 +0,0 @@ -SqliteDatabase in bdk::database - Rust

Struct bdk::database::SqliteDatabase

source ·
pub struct SqliteDatabase {
-    pub path: PathBuf,
-    pub connection: Connection,
-}
Expand description

Sqlite database stored on filesystem

-

This is a permanent storage solution for devices and platforms that provide a filesystem. -crate::database

-

Fields§

§path: PathBuf

Path on the local filesystem to store the sqlite file

-
§connection: Connection

A rusqlite connection object to the sqlite database

-

Implementations§

Instantiate a new SqliteDatabase instance by creating a connection -to the database stored at path

-

Trait Implementations§

Container for the operations
Create a new batch container
Consume and apply a batch of operations
Store a script_pubkey along with its keychain and child number.
Store a LocalUtxo
Store a raw transaction
Store the metadata of a transaction
Store the last derivation index for a given keychain.
Store the sync time
Delete a script_pubkey given the keychain and its child number.
Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more
Delete a LocalUtxo given its [OutPoint]
Delete a raw transaction given its [Txid]
Delete the metadata of a transaction and optionally the raw transaction itself
Delete the last derivation index for a keychain.
Reset the sync time to None Read more
Type that contains the configuration
Create a new instance given a configuration
Read and checks the descriptor checksum for a given keychain. Read more
Return the list of script_pubkeys
Return the list of LocalUtxos
Return the list of raw transactions
Return the list of transactions metadata
Fetch a script_pubkey given the child number of a keychain.
Fetch the keychain and child number of a given script_pubkey
Fetch a LocalUtxo given its [OutPoint]
Fetch a raw transaction given its [Txid]
Fetch the transaction metadata and optionally also the raw transaction
Return the last derivation index for a keychain.
Return the sync time, if present
Increment the last derivation index for a keychain and return it Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/struct.SyncTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/struct.SyncTime.html deleted file mode 100644 index 00cfb9affd..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/struct.SyncTime.html +++ /dev/null @@ -1,13 +0,0 @@ -SyncTime in bdk::database - Rust

Struct bdk::database::SyncTime

source ·
pub struct SyncTime {
-    pub block_time: BlockTime,
-}
Expand description

Blockchain state at the time of syncing

-

Contains only the block time and height at the moment

-

Fields§

§block_time: BlockTime

Block timestamp and height at the time of sync

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
This method tests for self and other values to be equal, and is used -by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

-

Calls U::from(self).

-

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchDatabase.html deleted file mode 100644 index ac39984fe3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchDatabase.html +++ /dev/null @@ -1,12 +0,0 @@ -BatchDatabase in bdk::database - Rust

Trait bdk::database::BatchDatabase

source ·
pub trait BatchDatabase: Database {
-    type Batch: BatchOperations;
-
-    fn begin_batch(&self) -> Self::Batch;
-    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
-}
Expand description

Trait for a database that supports batch operations

-

This trait defines the methods to start and apply a batch of operations.

-

Required Associated Types§

Container for the operations

-

Required Methods§

Create a new batch container

-

Consume and apply a batch of operations

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchOperations.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchOperations.html deleted file mode 100644 index 7e60f5b883..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchOperations.html +++ /dev/null @@ -1,34 +0,0 @@ -BatchOperations in bdk::database - Rust
pub trait BatchOperations {
-
Show 13 methods fn set_script_pubkey(
        &mut self,
        script: &Script,
        keychain: KeychainKind,
        child: u32
    ) -> Result<(), Error>; - fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error>; - fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; - fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>; - fn set_last_index(
        &mut self,
        keychain: KeychainKind,
        value: u32
    ) -> Result<(), Error>; - fn set_sync_time(&mut self, sync_time: SyncTime) -> Result<(), Error>; - fn del_script_pubkey_from_path(
        &mut self,
        keychain: KeychainKind,
        child: u32
    ) -> Result<Option<Script>, Error>; - fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(KeychainKind, u32)>, Error>; - fn del_utxo(
        &mut self,
        outpoint: &OutPoint
    ) -> Result<Option<LocalUtxo>, Error>; - fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>; - fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; - fn del_last_index(
        &mut self,
        keychain: KeychainKind
    ) -> Result<Option<u32>, Error>; - fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error>; -
}
Expand description

Trait for operations that can be batched

-

This trait defines the list of operations that must be implemented on the Database type and -the BatchDatabase::Batch type.

-

Required Methods§

Store a script_pubkey along with its keychain and child number.

-

Store a LocalUtxo

-

Store a raw transaction

-

Store the metadata of a transaction

-

Store the last derivation index for a given keychain.

-

Store the sync time

-

Delete a script_pubkey given the keychain and its child number.

-

Delete the data related to a specific script_pubkey, meaning the keychain and the child -number.

-

Delete a LocalUtxo given its [OutPoint]

-

Delete a raw transaction given its [Txid]

-

Delete the metadata of a transaction and optionally the raw transaction itself

-

Delete the last derivation index for a keychain.

-

Reset the sync time to None

-

Returns the removed value

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html deleted file mode 100644 index 75c56fd3ec..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html +++ /dev/null @@ -1,9 +0,0 @@ -ConfigurableDatabase in bdk::database - Rust
pub trait ConfigurableDatabase: Database + Sized {
-    type Config: Debug;
-
-    fn from_config(config: &Self::Config) -> Result<Self, Error>;
-}
Expand description

Trait for Database types that can be created given a configuration

-

Required Associated Types§

Type that contains the configuration

-

Required Methods§

Create a new instance given a configuration

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.Database.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.Database.html deleted file mode 100644 index 384ff5377b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.Database.html +++ /dev/null @@ -1,35 +0,0 @@ -Database in bdk::database - Rust

Trait bdk::database::Database

source ·
pub trait Database: BatchOperations {
-
Show 13 methods fn check_descriptor_checksum<B: AsRef<[u8]>>(
        &mut self,
        keychain: KeychainKind,
        bytes: B
    ) -> Result<(), Error>; - fn iter_script_pubkeys(
        &self,
        keychain: Option<KeychainKind>
    ) -> Result<Vec<Script>, Error>; - fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error>; - fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>; - fn iter_txs(
        &self,
        include_raw: bool
    ) -> Result<Vec<TransactionDetails>, Error>; - fn get_script_pubkey_from_path(
        &self,
        keychain: KeychainKind,
        child: u32
    ) -> Result<Option<Script>, Error>; - fn get_path_from_script_pubkey(
        &self,
        script: &Script
    ) -> Result<Option<(KeychainKind, u32)>, Error>; - fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>; - fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; - fn get_tx(
        &self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; - fn get_last_index(
        &self,
        keychain: KeychainKind
    ) -> Result<Option<u32>, Error>; - fn get_sync_time(&self) -> Result<Option<SyncTime>, Error>; - fn increment_last_index(
        &mut self,
        keychain: KeychainKind
    ) -> Result<u32, Error>; -
}
Expand description

Trait for reading data from a database

-

This traits defines the operations that can be used to read data out of a database

-

Required Methods§

Read and checks the descriptor checksum for a given keychain.

-

Should return Error::ChecksumMismatch if the -checksum doesn’t match. If there’s no checksum in the database, simply store it for the -next time.

-

Return the list of script_pubkeys

-

Return the list of LocalUtxos

-

Return the list of raw transactions

-

Return the list of transactions metadata

-

Fetch a script_pubkey given the child number of a keychain.

-

Fetch the keychain and child number of a given script_pubkey

-

Fetch a LocalUtxo given its [OutPoint]

-

Fetch a raw transaction given its [Txid]

-

Fetch the transaction metadata and optionally also the raw transaction

-

Return the last derivation index for a keychain.

-

Return the sync time, if present

-

Increment the last derivation index for a keychain and return it

-

It should insert and return 0 if not present in the database

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum.html index 86ae9f0e9f..93a273e23c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum.html @@ -1,3 +1,2 @@ -calc_checksum in bdk::descriptor::checksum - Rust
pub fn calc_checksum(desc: &str) -> Result<String, DescriptorError>
Expand description

Compute the checksum of a descriptor, excludes any existing checksum in the descriptor string from the calculation

+calc_checksum in bdk::descriptor::checksum - Rust
pub fn calc_checksum(desc: &str) -> Result<String, DescriptorError>
Expand description

Compute the checksum of a descriptor, excludes any existing checksum in the descriptor string from the calculation

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum_bytes.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum_bytes.html index d04be67e0e..120e357f66 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum_bytes.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum_bytes.html @@ -1,3 +1,2 @@ -calc_checksum_bytes in bdk::descriptor::checksum - Rust
pub fn calc_checksum_bytes(desc: &str) -> Result<[u8; 8], DescriptorError>
Expand description

Compute the checksum bytes of a descriptor, excludes any existing checksum in the descriptor string from the calculation

+calc_checksum_bytes in bdk::descriptor::checksum - Rust
pub fn calc_checksum_bytes(desc: &str) -> Result<[u8; 8], DescriptorError>
Expand description

Compute the checksum bytes of a descriptor, excludes any existing checksum in the descriptor string from the calculation

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html index 5ec52b6912..bfcfb4e1f1 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html @@ -1,3 +1,2 @@ -get_checksum in bdk::descriptor::checksum - Rust

Function bdk::descriptor::checksum::get_checksum

source ·
pub fn get_checksum(desc: &str) -> Result<String, DescriptorError>
👎Deprecated since 0.24.0: Use new calc_checksum function which excludes any existing checksum in the descriptor string before calculating the checksum hash. See https://github.com/bitcoindevkit/bdk/pull/765.
Expand description

Compute the checksum of a descriptor

+get_checksum in bdk::descriptor::checksum - Rust

Function bdk::descriptor::checksum::get_checksum

source ·
pub fn get_checksum(desc: &str) -> Result<String, DescriptorError>
👎Deprecated since 0.24.0: Use new calc_checksum function which excludes any existing checksum in the descriptor string before calculating the checksum hash. See https://github.com/bitcoindevkit/bdk/pull/765.
Expand description

Compute the checksum of a descriptor

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum_bytes.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum_bytes.html index 7c9d89ea5b..02d90dbfd3 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum_bytes.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum_bytes.html @@ -1,3 +1,2 @@ -get_checksum_bytes in bdk::descriptor::checksum - Rust
pub fn get_checksum_bytes(desc: &str) -> Result<[u8; 8], DescriptorError>
👎Deprecated since 0.24.0: Use new calc_checksum_bytes function which excludes any existing checksum in the descriptor string before calculating the checksum hash bytes. See https://github.com/bitcoindevkit/bdk/pull/765.
Expand description

Compute the checksum bytes of a descriptor

+get_checksum_bytes in bdk::descriptor::checksum - Rust
pub fn get_checksum_bytes(desc: &str) -> Result<[u8; 8], DescriptorError>
👎Deprecated since 0.24.0: Use new calc_checksum_bytes function which excludes any existing checksum in the descriptor string before calculating the checksum hash bytes. See https://github.com/bitcoindevkit/bdk/pull/765.
Expand description

Compute the checksum bytes of a descriptor

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html index 0ef4d02787..b4d73cedbf 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html @@ -1,5 +1,4 @@ -bdk::descriptor::checksum - Rust

Module bdk::descriptor::checksum

source ·
Expand description

Descriptor checksum

+bdk::descriptor::checksum - Rust

Module bdk::descriptor::checksum

source ·
Expand description

Descriptor checksum

This module contains a re-implementation of the function used by Bitcoin Core to calculate the checksum of a descriptor

Functions

Compute the checksum of a descriptor, excludes any existing checksum in the descriptor string from the calculation
Compute the checksum bytes of a descriptor, excludes any existing checksum in the descriptor string from the calculation
get_checksumDeprecated
Compute the checksum of a descriptor
Compute the checksum bytes of a descriptor
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html index 0bbeb10d5a..b44ba87ed9 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html @@ -1,5 +1,4 @@ -Descriptor in bdk::descriptor - Rust
pub enum Descriptor<Pk>where
    Pk: MiniscriptKey,
{ +Descriptor in bdk::descriptor - Rust
pub enum Descriptor<Pk>where
    Pk: MiniscriptKey,
{ Bare(Bare<Pk>), Pkh(Pkh<Pk>), Wpkh(Wpkh<Pk>), @@ -132,16 +131,16 @@ default(0x02) y-coordinate.

assert_eq!(result.to_string(), "tr(03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115)#6qm9h8ym");
Errors

This function will return an error if hardened derivation is attempted.

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
Formats the value using the given formatter. Read more
Extract the spending policy
Run a predicate on every key in the descriptor, returning whether +

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the minimum value (in satoshis) that an output should have to be broadcastable.
Deserialize this value from the given Serde deserializer. Read more
Formats the value using the given formatter. Read more
Extract the spending policy
Run a predicate on every key in the descriptor, returning whether the predicate returned true for every key Read more
Run a predicate on every key in the descriptor, returning whether -the predicate returned true for any key Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
The associated error which can be returned from parsing.
Parses a string s to return a value of this type. Read more

Parse an expression tree into a descriptor.

+the predicate returned true for any key Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
The associated error which can be returned from parsing.
Parses a string s to return a value of this type. Read more

Parse an expression tree into a descriptor.

Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Convert the object into an abstract policy
This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
Serialize this value into the given Serde serializer. Read more

Converts a descriptor using abstract keys to one using specific keys.

-
The associated output type. This must be Self<Q>.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+operator. Read more
Serialize this value into the given Serde serializer. Read more

Converts a descriptor using abstract keys to one using specific keys.

+
The associated output type. This must be Self<Q>.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.DescriptorPublicKey.html index 0493530060..c37e18af97 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.DescriptorPublicKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.DescriptorPublicKey.html @@ -1,5 +1,4 @@ -DescriptorPublicKey in bdk::descriptor - Rust

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
The associated error which can be returned from parsing.
Parses a string s to return a value of this type. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Turn the key into a DescriptorKey within the requested ScriptContext
The associated [sha256::Hash] for this [MiniscriptKey], +

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
The associated error which can be returned from parsing.
Parses a string s to return a value of this type. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Turn the key into a DescriptorKey within the requested ScriptContext
The associated [sha256::Hash] for this [MiniscriptKey], used in the hash256 fragment. Read more
The associated [hash256::Hash] for this [MiniscriptKey], used in the hash256 fragment. Read more
The associated [ripedmd160::Hash] for this [MiniscriptKey] type. used in the ripemd160 fragment Read more
The associated [hash160::Hash] for this [MiniscriptKey] type. @@ -31,8 +30,8 @@ used in the hash160 fragment Read more
Read more
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+operator. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html index e9741a5f0c..2fb5418f73 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html @@ -1,5 +1,4 @@ -Legacy in bdk::descriptor - Rust

Enum bdk::descriptor::Legacy

pub enum Legacy {}
Expand description

Legacy ScriptContext +Legacy in bdk::descriptor - Rust

Enum bdk::descriptor::Legacy

pub enum Legacy {}
Expand description

Legacy ScriptContext To be used as P2SH scripts For creation of Bare scriptpubkeys, construct the Miniscript under Bare ScriptContext

@@ -44,8 +43,8 @@ scripts over 3600 bytes are invalid. Post Tapscript upgrade, this would have to consider other nodes. This does NOT recursively check the miniscript fragments. Read more
Check the consensus + policy(if not disabled) rules that are not based satisfaction Read more
Check the consensus + policy(if not disabled) rules including the -ones for satisfaction Read more
Check whether the top-level is type B
Other top level checks that are context specific
Check top level consensus rules.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Returns whether the script context is Legacy
Returns whether the script context is Segwitv0
Returns whether the script context is Tap, aka Taproot or Segwit V1

Returns the argument unchanged.

+ones for satisfaction Read more
Check whether the top-level is type B
Other top level checks that are context specific
Check top level consensus rules.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Returns whether the script context is Legacy
Returns whether the script context is Segwitv0
Returns whether the script context is Tap, aka Taproot or Segwit V1

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html index 5685161db5..113739e55f 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html @@ -1,5 +1,4 @@ -Segwitv0 in bdk::descriptor - Rust

Enum bdk::descriptor::Segwitv0

pub enum Segwitv0 {}
Expand description

Segwitv0 ScriptContext

+Segwitv0 in bdk::descriptor - Rust

Enum bdk::descriptor::Segwitv0

pub enum Segwitv0 {}
Expand description

Segwitv0 ScriptContext

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= @@ -41,8 +40,8 @@ Note that this includes the serialization prefix. Returns 34/66 for Bare/Legacy based on key compressedness 34 for Segwitv0, 33 for Tap Read more
Local helper function to display error messages with context
The type of signature required for satisfaction
Check the consensus + policy(if not disabled) rules that are not based satisfaction Read more
Check the consensus + policy(if not disabled) rules including the -ones for satisfaction Read more
Check whether the top-level is type B
Other top level checks that are context specific
Check top level consensus rules.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Returns whether the script context is Legacy
Returns whether the script context is Segwitv0
Returns whether the script context is Tap, aka Taproot or Segwit V1

Returns the argument unchanged.

+ones for satisfaction Read more
Check whether the top-level is type B
Other top level checks that are context specific
Check top level consensus rules.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Returns whether the script context is Legacy
Returns whether the script context is Segwitv0
Returns whether the script context is Tap, aka Taproot or Segwit V1

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Wildcard.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Wildcard.html index d9e35cbb30..060cf4e380 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Wildcard.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Wildcard.html @@ -1,5 +1,4 @@ -Wildcard in bdk::descriptor - Rust

Enum bdk::descriptor::Wildcard

pub enum Wildcard {
+Wildcard in bdk::descriptor - Rust

Enum bdk::descriptor::Wildcard

pub enum Wildcard {
     None,
     Unhardened,
     Hardened,
@@ -11,8 +10,8 @@
 by ==. Read more
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+operator. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html index 2d2917e9d1..752ab108a6 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html @@ -1,5 +1,4 @@ -Error in bdk::descriptor::error - Rust

Enum bdk::descriptor::error::Error

source ·
pub enum Error {
+Error in bdk::descriptor::error - Rust

Enum bdk::descriptor::error::Error

source ·
pub enum Error {
     InvalidHdKeyPath,
     InvalidDescriptorChecksum,
     HardenedDerivationXpub,
@@ -23,9 +22,9 @@
 
§

Pk(Error)

Key-related error

§

Miniscript(Error)

Miniscript error

§

Hex(Error)

Hex decoding error

-

Trait Implementations§

Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
The lower-level source of this error, if any. Read more
👎Deprecated since 1.42.0: use the Display impl or to_string()
👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+

Trait Implementations§

Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
The lower-level source of this error, if any. Read more
👎Deprecated since 1.42.0: use the Display impl or to_string()
👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.
Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
🔬This is a nightly-only experimental API. (provide_any)
Data providers should implement this method to provide all values they are able to +
🔬This is a nightly-only experimental API. (provide_any)
Data providers should implement this method to provide all values they are able to provide by using demand. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html index e94714d4e3..87045f3d66 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html @@ -1,3 +1,2 @@ -bdk::descriptor::error - Rust

Module bdk::descriptor::error

source ·
Expand description

Descriptor errors

+bdk::descriptor::error - Rust

Module bdk::descriptor::error

source ·
Expand description

Descriptor errors

Enums

Errors related to the parsing and usage of descriptors
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html index f829f28390..e013203ffc 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html @@ -1,5 +1,4 @@ -bdk::descriptor - Rust

Module bdk::descriptor

source ·
Expand description

Descriptors

+bdk::descriptor - Rust

Module bdk::descriptor

source ·
Expand description

Descriptors

This module contains generic utilities to work with descriptors, plus some re-exported types from [miniscript].

Re-exports

pub use self::checksum::calc_checksum;
pub use self::error::Error as DescriptorError;
pub use self::policy::Policy;

Modules

Descriptor checksum
Descriptor errors
Descriptor policy
Descriptor templates

Structs

An extended key with origin, derivation path, and wildcard.
Top-level script AST type

Enums

Script descriptor
The descriptor pubkey, either a single pubkey or an xpub.
Legacy ScriptContext diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html index 327d17f210..c4d3a501a7 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html @@ -1,5 +1,4 @@ -BuildSatisfaction in bdk::descriptor::policy - Rust
pub enum BuildSatisfaction<'a> {
+BuildSatisfaction in bdk::descriptor::policy - Rust
pub enum BuildSatisfaction<'a> {
     None,
     Psbt(&'a Psbt),
     PsbtTimelocks {
@@ -15,8 +14,8 @@
 
§input_max_height: u32

The highest confirmation height between the inputs CSV should consider different inputs, but we consider the worst condition for the tx as whole

Like Psbt variant and also check for expired timelocks

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PkOrF.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PkOrF.html index 766f53cd52..56c0b6f5e1 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PkOrF.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PkOrF.html @@ -1,5 +1,4 @@ -PkOrF in bdk::descriptor::policy - Rust

Enum bdk::descriptor::policy::PkOrF

source ·
pub enum PkOrF {
+PkOrF in bdk::descriptor::policy - Rust

Enum bdk::descriptor::policy::PkOrF

source ·
pub enum PkOrF {
     Pubkey(PublicKey),
     XOnlyPubkey(XOnlyPublicKey),
     Fingerprint(Fingerprint),
@@ -7,10 +6,10 @@
 

Variants§

§

Pubkey(PublicKey)

A legacy public key

§

XOnlyPubkey(XOnlyPublicKey)

A x-only public key

§

Fingerprint(Fingerprint)

An extended key fingerprint

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method tests for self and other values to be equal, and is used +

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html index 5276fe6dd2..d15e1bb1a9 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html @@ -1,5 +1,4 @@ -PolicyError in bdk::descriptor::policy - Rust
pub enum PolicyError {
+PolicyError in bdk::descriptor::policy - Rust
pub enum PolicyError {
     NotEnoughItemsSelected(String),
     IndexOutOfRange(usize),
     AddOnLeaf,
@@ -13,11 +12,11 @@
 
§

AddOnPartialComplete

Can not add to an item that is Satisfaction::PartialComplete

§

MixedTimelockUnits

Can not merge CSV or timelock values unless both are less than or both are equal or greater than 500_000_000

§

IncompatibleConditions

Incompatible conditions (not currently used)

-

Trait Implementations§

Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
The lower-level source of this error, if any. Read more
👎Deprecated since 1.42.0: use the Display impl or to_string()
👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
Converts to this type from the input type.
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used +

Trait Implementations§

Formats the value using the given formatter. Read more
Formats the value using the given formatter. Read more
The lower-level source of this error, if any. Read more
👎Deprecated since 1.42.0: use the Display impl or to_string()
👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type based access to context intended for error reports. Read more
Converts to this type from the input type.
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+sufficient, and should not be overridden without very good reason. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
🔬This is a nightly-only experimental API. (provide_any)
Data providers should implement this method to provide all values they are able to +
🔬This is a nightly-only experimental API. (provide_any)
Data providers should implement this method to provide all values they are able to provide by using demand. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html index 466ab619f6..67949fe851 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html @@ -1,5 +1,4 @@ -Satisfaction in bdk::descriptor::policy - Rust
pub enum Satisfaction {
+Satisfaction in bdk::descriptor::policy - Rust
pub enum Satisfaction {
     Partial {
         n: usize,
         m: usize,
@@ -34,11 +33,11 @@
 
§

Complete

Fields

§condition: Condition

Extra conditions that also need to be satisfied

Can satisfy the policy item

§

None

Cannot satisfy or contribute to the policy item

-

Implementations§

Returns whether the Satisfaction is a leaf item

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used +

Implementations§

Returns whether the Satisfaction is a leaf item

+

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html index 10d505a0d1..c421e4ae1b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html @@ -1,5 +1,4 @@ -SatisfiableItem in bdk::descriptor::policy - Rust
pub enum SatisfiableItem {
+SatisfiableItem in bdk::descriptor::policy - Rust
pub enum SatisfiableItem {
     EcdsaSignature(PkOrF),
     SchnorrSignature(PkOrF),
     Sha256Preimage {
@@ -49,12 +48,12 @@
 
§

Thresh

Fields

§items: Vec<Policy>

The policy items

§threshold: usize

The required threshold count

Threshold items with threshold count

-

Implementations§

Returns whether the SatisfiableItem is a leaf item

-

Returns a unique id for the SatisfiableItem

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used +

Implementations§

Returns whether the SatisfiableItem is a leaf item

+

Returns a unique id for the SatisfiableItem

+

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html index e3b80b58de..caab7e8957 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html @@ -1,5 +1,4 @@ -bdk::descriptor::policy - Rust

Module bdk::descriptor::policy

source ·
Expand description

Descriptor policy

+bdk::descriptor::policy - Rust

Module bdk::descriptor::policy

source ·
Expand description

Descriptor policy

This module implements the logic to extract and represent the spending policies of a descriptor in a more human-readable format.

This is an EXPERIMENTAL feature, API and other major changes are expected.

@@ -13,6 +12,6 @@ in a more human-readable format.

let signers = Arc::new(SignersContainer::build(key_map, &extended_desc, &secp)); let policy = extended_desc.extract_policy(&signers, BuildSatisfaction::None, &secp)?; -println!("policy: {}", serde_json::to_string(&policy)?);
+println!("policy: {}", serde_json::to_string(&policy).unwrap());

Structs

An extra condition that must be satisfied but that is out of control of the user TODO: use bitcoin::LockTime and bitcoin::Sequence
Descriptor spending policy

Enums

Options to build the satisfaction field in the policy
A unique identifier for a key
Errors that can happen while extracting and manipulating policies
Represent if and how much a policy item is satisfied by the wallet’s descriptor
An item that needs to be satisfied

Type Definitions

Type for a map of sets of Condition items keyed by each set’s index
Type for a map of folded sets of Condition items keyed by a vector of the combined set’s indexes
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html index abf2f325d6..391aa5e547 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html @@ -1,18 +1,17 @@ -Condition in bdk::descriptor::policy - Rust

Struct bdk::descriptor::policy::Condition

source ·
pub struct Condition {
+Condition in bdk::descriptor::policy - Rust

Struct bdk::descriptor::policy::Condition

source ·
pub struct Condition {
     pub csv: Option<Sequence>,
     pub timelock: Option<LockTime>,
 }
Expand description

An extra condition that must be satisfied but that is out of control of the user TODO: use bitcoin::LockTime and bitcoin::Sequence

Fields§

§csv: Option<Sequence>

Optional CheckSequenceVerify condition

§timelock: Option<LockTime>

Optional timelock condition

-

Implementations§

Returns true if there are no extra conditions to verify

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method tests for self and other values to be equal, and is used +

Implementations§

Returns true if there are no extra conditions to verify

+

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+operator. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html index f60c60833f..a0450e6275 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html @@ -1,5 +1,4 @@ -Policy in bdk::descriptor::policy - Rust

Struct bdk::descriptor::policy::Policy

source ·
pub struct Policy {
+Policy in bdk::descriptor::policy - Rust

Struct bdk::descriptor::policy::Policy

source ·
pub struct Policy {
     pub id: String,
     pub item: SatisfiableItem,
     pub satisfaction: Satisfaction,
@@ -9,17 +8,17 @@
 
§item: SatisfiableItem

Type of this policy node

§satisfaction: Satisfaction

How much a given PSBT already satisfies this policy node in terms of signatures

§contribution: Satisfaction

How the wallet’s descriptor can satisfy this policy node

-

Implementations§

Return whether or not a specific path in the policy tree is required to unambiguously +

Implementations§

Return whether or not a specific path in the policy tree is required to unambiguously create a transaction

What this means is that for some spending policies the user should select which paths in the tree it intends to satisfy while signing, because the transaction must be created differently based on that.

-

Return the conditions that are set by the spending policy for a given path in the +

Return the conditions that are set by the spending policy for a given path in the policy tree

-

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used +

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==. Read more
This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+sufficient, and should not be overridden without very good reason. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html index ae8dc5722c..38584cfa90 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html @@ -1,3 +1,2 @@ -ConditionMap in bdk::descriptor::policy - Rust

Type Definition bdk::descriptor::policy::ConditionMap

source ·
pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
Expand description

Type for a map of sets of Condition items keyed by each set’s index

+ConditionMap in bdk::descriptor::policy - Rust

Type Definition bdk::descriptor::policy::ConditionMap

source ·
pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
Expand description

Type for a map of sets of Condition items keyed by each set’s index

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html index f30a400000..39c2bef089 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html @@ -1,3 +1,2 @@ -FoldedConditionMap in bdk::descriptor::policy - Rust

Type Definition bdk::descriptor::policy::FoldedConditionMap

source ·
pub type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
Expand description

Type for a map of folded sets of Condition items keyed by a vector of the combined set’s indexes

+FoldedConditionMap in bdk::descriptor::policy - Rust

Type Definition bdk::descriptor::policy::FoldedConditionMap

source ·
pub type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
Expand description

Type for a map of folded sets of Condition items keyed by a vector of the combined set’s indexes

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DescriptorXKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DescriptorXKey.html index 8095bf0a13..b765e383b8 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DescriptorXKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DescriptorXKey.html @@ -1,5 +1,4 @@ -DescriptorXKey in bdk::descriptor - Rust
pub struct DescriptorXKey<K>where
    K: InnerXKey,
{ +DescriptorXKey in bdk::descriptor - Rust
pub struct DescriptorXKey<K>where
    K: InnerXKey,
{ pub origin: Option<(Fingerprint, DerivationPath)>, pub xkey: K, pub derivation_path: DerivationPath, @@ -51,8 +50,8 @@ origin’s and key’s paths.

by ==. Read more
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

+operator. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

-
The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file +
The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html index e4ad13a4b2..60f7fb2ba9 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html @@ -1,5 +1,4 @@ -Miniscript in bdk::descriptor - Rust

Struct bdk::descriptor::Miniscript

pub struct Miniscript<Pk, Ctx>where
    Pk: MiniscriptKey,
    Ctx: ScriptContext,
{ +Miniscript in bdk::descriptor - Rust

Struct bdk::descriptor::Miniscript

pub struct Miniscript<Pk, Ctx>where
    Pk: MiniscriptKey,
    Ctx: ScriptContext,
{ pub node: Terminal<Pk, Ctx>, pub ty: Type, pub ext: ExtData, @@ -30,7 +29,7 @@ AST by traversing its branches. For the specific algorithm please see

Creates a new [PkIter] iterator that will iterate over all plain public keys (and not key hash values) present in Miniscript items within AST by traversing all its branches. For the specific algorithm please see [PkIter::next] function.

-

Enumerates all child nodes of the current AST node (self) and returns a Vec referencing +

Enumerates all child nodes of the current AST node (self) and returns a Vec referencing them.

Returns child node with given index, if any

Returns Option::Some with cloned n’th public key from the current miniscript item, @@ -130,7 +129,7 @@ This can occur if the miniscript contains a

  • Timelock combination
  • Contains a spend that exceeds resource limits
  • -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    Extract the spending policy
    Run a predicate on every key in the descriptor, returning whether +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    Extract the spending policy
    Run a predicate on every key in the descriptor, returning whether the predicate returned true for every key Read more
    Run a predicate on every key in the descriptor, returning whether the predicate returned true for any key Read more

    Parse a Miniscript from string and perform sanity checks See Miniscript::from_str_insane to parse scripts from string that @@ -150,13 +149,13 @@ The type information and extra_properties can be deterministically determined by the ast.

    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Translates a struct from one generic to another where the translation +operator. Read more

    Serialize this value into the given Serde serializer. Read more

    Translates a struct from one generic to another where the translation for Pk is provided by [Translator]

    The associated output type. This must be Self<Q>.

    Eq of Miniscript must depend only on node and not the type information. The type information and extra_properties can be deterministically determined by the ast.

    -

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html index 4af201d67f..f72226c66c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html @@ -1,5 +1,4 @@ -bdk::descriptor::template - Rust

    Module bdk::descriptor::template

    source ·
    Expand description

    Descriptor templates

    +bdk::descriptor::template - Rust

    Module bdk::descriptor::template

    source ·
    Expand description

    Descriptor templates

    This module contains the definition of various common script templates that are ready to be used. See the documentation of each template for an example.

    Structs

    BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/*)
    BIP44 public template. Expands to pkh(key/{0,1}/*)
    BIP49 template. Expands to sh(wpkh(key/49'/{0,1}'/0'/{0,1}/*))
    BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))
    BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/*)
    BIP84 public template. Expands to wpkh(key/{0,1}/*)
    P2PKH template. Expands to a descriptor pkh(key)
    P2WPKH template. Expands to a descriptor wpkh(key)
    P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))

    Traits

    Trait for descriptor templates that can be built into a full descriptor

    Type Definitions

    Type alias for the return type of DescriptorTemplate, descriptor! and others
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html index bd44d21c6e..30c54c6416 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html @@ -1,22 +1,20 @@ -Bip44 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip44

    source ·
    pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
    Expand description

    BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/*)

    +Bip44 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip44

    source ·
    pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
    Expand description

    BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/*)

    Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).

    See Bip44Public for a template that can work with a xpub/tpub.

    Example

    use bdk::template::Bip44;
     
     let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet = Wallet::new(
    +let mut wallet = Wallet::new_no_persist(
         Bip44(key.clone(), KeychainKind::External),
         Some(Bip44(key, KeychainKind::Internal)),
         Network::Testnet,
    -    MemoryDatabase::default()
     )?;
     
    -assert_eq!(wallet.get_address(New)?.to_string(), "mmogjc7HJEZkrLqyQYqJmxUqFaC7i4uf89");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDCuorCpzvYS2LCD75BR46KHE8GdDeg1wsAgNZeNr6DaB5gQK1o14uErKwKLuFmeemkQ6N2m3rNgvctdJLyr7nwu2yia7413Hhg8WWE44cgT/0/*)#5wrnv0xt");
    -

    Tuple Fields§

    §0: K§1: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +assert_eq!(wallet.get_address(New).to_string(), "mmogjc7HJEZkrLqyQYqJmxUqFaC7i4uf89"); +assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDCuorCpzvYS2LCD75BR46KHE8GdDeg1wsAgNZeNr6DaB5gQK1o14uErKwKLuFmeemkQ6N2m3rNgvctdJLyr7nwu2yia7413Hhg8WWE44cgT/0/*)#5wrnv0xt");
    +

    Tuple Fields§

    §0: K§1: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html index ab747889bc..820ecfa005 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html @@ -1,5 +1,4 @@ -Bip44Public in bdk::descriptor::template - Rust
    pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub Fingerprint, pub KeychainKind);
    Expand description

    BIP44 public template. Expands to pkh(key/{0,1}/*)

    +Bip44Public in bdk::descriptor::template - Rust
    pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub Fingerprint, pub KeychainKind);
    Expand description

    BIP44 public template. Expands to pkh(key/{0,1}/*)

    This assumes that the key used has already been derived with m/44'/0'/0' for Mainnet or m/44'/1'/0' for Testnet.

    This template requires the parent fingerprint to populate correctly the metadata of PSBTs.

    See Bip44 for a template that does the full derivation, but requires private data @@ -9,17 +8,16 @@ for the key.

    let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?; let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?; -let wallet = Wallet::new( +let mut wallet = Wallet::new_no_persist( Bip44Public(key.clone(), fingerprint, KeychainKind::External), Some(Bip44Public(key, fingerprint, KeychainKind::Internal)), Network::Testnet, - MemoryDatabase::default() )?; -assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR"); -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#cfhumdqz");
    -

    Tuple Fields§

    §0: K§1: Fingerprint§2: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +assert_eq!(wallet.get_address(New).to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR"); +assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#cfhumdqz");
    +

    Tuple Fields§

    §0: K§1: Fingerprint§2: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html index f34bbe0bf8..b454f4131a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html @@ -1,22 +1,20 @@ -Bip49 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip49

    source ·
    pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    Expand description

    BIP49 template. Expands to sh(wpkh(key/49'/{0,1}'/0'/{0,1}/*))

    +Bip49 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip49

    source ·
    pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    Expand description

    BIP49 template. Expands to sh(wpkh(key/49'/{0,1}'/0'/{0,1}/*))

    Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).

    See Bip49Public for a template that can work with a xpub/tpub.

    Example

    use bdk::template::Bip49;
     
     let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet = Wallet::new(
    +let mut wallet = Wallet::new_no_persist(
         Bip49(key.clone(), KeychainKind::External),
         Some(Bip49(key, KeychainKind::Internal)),
         Network::Testnet,
    -    MemoryDatabase::default()
     )?;
     
    -assert_eq!(wallet.get_address(New)?.to_string(), "2N4zkWAoGdUv4NXhSsU8DvS5MB36T8nKHEB");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDDYr4kdnZgjjShzYNjZUZXUUtpXaofdkMaipyS8ThEh45qFmhT4hKYways7UXmg6V7het1QiFo9kf4kYUXyDvV4rHEyvSpys9pjCB3pukxi/0/*))#s9vxlc8e");
    -

    Tuple Fields§

    §0: K§1: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +assert_eq!(wallet.get_address(New).to_string(), "2N4zkWAoGdUv4NXhSsU8DvS5MB36T8nKHEB"); +assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDDYr4kdnZgjjShzYNjZUZXUUtpXaofdkMaipyS8ThEh45qFmhT4hKYways7UXmg6V7het1QiFo9kf4kYUXyDvV4rHEyvSpys9pjCB3pukxi/0/*))#s9vxlc8e");
    +

    Tuple Fields§

    §0: K§1: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html index 4233e3a1b7..4b69018f10 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html @@ -1,5 +1,4 @@ -Bip49Public in bdk::descriptor::template - Rust
    pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);
    Expand description

    BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))

    +Bip49Public in bdk::descriptor::template - Rust
    pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);
    Expand description

    BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))

    This assumes that the key used has already been derived with m/49'/0'/0' for Mainnet or m/49'/1'/0' for Testnet.

    This template requires the parent fingerprint to populate correctly the metadata of PSBTs.

    See Bip49 for a template that does the full derivation, but requires private data @@ -9,17 +8,16 @@ for the key.

    let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?; let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?; -let wallet = Wallet::new( +let mut wallet = Wallet::new_no_persist( Bip49Public(key.clone(), fingerprint, KeychainKind::External), Some(Bip49Public(key, fingerprint, KeychainKind::Internal)), Network::Testnet, - MemoryDatabase::default() )?; -assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt"); -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#3tka9g0q");
    -

    Tuple Fields§

    §0: K§1: Fingerprint§2: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +assert_eq!(wallet.get_address(New).to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt"); +assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#3tka9g0q");
    +

    Tuple Fields§

    §0: K§1: Fingerprint§2: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html index f1d69371d9..ba6f31c57e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html @@ -1,22 +1,20 @@ -Bip84 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip84

    source ·
    pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    Expand description

    BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/*)

    +Bip84 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip84

    source ·
    pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    Expand description

    BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/*)

    Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).

    See Bip84Public for a template that can work with a xpub/tpub.

    Example

    use bdk::template::Bip84;
     
     let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet = Wallet::new(
    +let mut wallet = Wallet::new_no_persist(
         Bip84(key.clone(), KeychainKind::External),
         Some(Bip84(key, KeychainKind::Internal)),
         Network::Testnet,
    -    MemoryDatabase::default()
     )?;
     
    -assert_eq!(wallet.get_address(New)?.to_string(), "tb1qhl85z42h7r4su5u37rvvw0gk8j2t3n9y7zsg4n");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDDc5mum24DekpNw92t6fHGp8Gr2JjF9J7i4TZBtN6Vp8xpAULG5CFaKsfugWa5imhrQQUZKXe261asP5koDHo5bs3qNTmf3U3o4v9SaB8gg/0/*)#6kfecsmr");
    -

    Tuple Fields§

    §0: K§1: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +assert_eq!(wallet.get_address(New).to_string(), "tb1qhl85z42h7r4su5u37rvvw0gk8j2t3n9y7zsg4n"); +assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDDc5mum24DekpNw92t6fHGp8Gr2JjF9J7i4TZBtN6Vp8xpAULG5CFaKsfugWa5imhrQQUZKXe261asP5koDHo5bs3qNTmf3U3o4v9SaB8gg/0/*)#6kfecsmr");
    +

    Tuple Fields§

    §0: K§1: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html index e10efcd032..5d8a679fbc 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html @@ -1,5 +1,4 @@ -Bip84Public in bdk::descriptor::template - Rust
    pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);
    Expand description

    BIP84 public template. Expands to wpkh(key/{0,1}/*)

    +Bip84Public in bdk::descriptor::template - Rust
    pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);
    Expand description

    BIP84 public template. Expands to wpkh(key/{0,1}/*)

    This assumes that the key used has already been derived with m/84'/0'/0' for Mainnet or m/84'/1'/0' for Testnet.

    This template requires the parent fingerprint to populate correctly the metadata of PSBTs.

    See Bip84 for a template that does the full derivation, but requires private data @@ -9,17 +8,16 @@ for the key.

    let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?; let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?; -let wallet = Wallet::new( +let mut wallet = Wallet::new_no_persist( Bip84Public(key.clone(), fingerprint, KeychainKind::External), Some(Bip84Public(key, fingerprint, KeychainKind::Internal)), Network::Testnet, - MemoryDatabase::default() )?; -assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7"); -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#dhu402yv");
    -

    Tuple Fields§

    §0: K§1: Fingerprint§2: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +assert_eq!(wallet.get_address(New).to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7"); +assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#dhu402yv");
    +

    Tuple Fields§

    §0: K§1: Fingerprint§2: KeychainKind

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html index 5413a68d73..bec74b5e8a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html @@ -1,23 +1,17 @@ -P2Pkh in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::P2Pkh

    source ·
    pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
    Expand description

    P2PKH template. Expands to a descriptor pkh(key)

    +P2Pkh in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::P2Pkh

    source ·
    pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
    Expand description

    P2PKH template. Expands to a descriptor pkh(key)

    Example

    use bdk::template::P2Pkh;
     
     let key =
         bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -let wallet = Wallet::new(
    -    P2Pkh(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    +let mut wallet = Wallet::new_no_persist(P2Pkh(key), None, Network::Testnet)?;
     
     assert_eq!(
    -    wallet.get_address(New)?.to_string(),
    +    wallet.get_address(New).to_string(),
         "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
     );
    -

    Tuple Fields§

    §0: K

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Tuple Fields§

    §0: K

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html index 58f559e143..53682051c1 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html @@ -1,23 +1,18 @@ -P2Wpkh in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::P2Wpkh

    source ·
    pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
    Expand description

    P2WPKH template. Expands to a descriptor wpkh(key)

    +P2Wpkh in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::P2Wpkh

    source ·
    pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
    Expand description

    P2WPKH template. Expands to a descriptor wpkh(key)

    Example

    use bdk::template::P2Wpkh;
    +use bdk::wallet::AddressIndex::New;
     
     let key =
         bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -let wallet = Wallet::new(
    -    P2Wpkh(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    +let mut wallet = Wallet::new_no_persist(P2Wpkh(key), None, Network::Testnet)?;
     
     assert_eq!(
    -    wallet.get_address(New)?.to_string(),
    +    wallet.get_address(New).to_string(),
         "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
     );
    -

    Tuple Fields§

    §0: K

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Tuple Fields§

    §0: K

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html index e96636285c..a12591a727 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html @@ -1,23 +1,18 @@ -P2Wpkh_P2Sh in bdk::descriptor::template - Rust
    pub struct P2Wpkh_P2Sh<K: IntoDescriptorKey<Segwitv0>>(pub K);
    Expand description

    P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))

    +P2Wpkh_P2Sh in bdk::descriptor::template - Rust
    pub struct P2Wpkh_P2Sh<K: IntoDescriptorKey<Segwitv0>>(pub K);
    Expand description

    P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))

    Example

    use bdk::template::P2Wpkh_P2Sh;
    +use bdk::wallet::AddressIndex;
     
     let key =
         bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -let wallet = Wallet::new(
    -    P2Wpkh_P2Sh(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    +let mut wallet = Wallet::new_no_persist(P2Wpkh_P2Sh(key), None, Network::Testnet)?;
     
     assert_eq!(
    -    wallet.get_address(New)?.to_string(),
    +    wallet.get_address(AddressIndex::New).to_string(),
         "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
     );
    -

    Tuple Fields§

    §0: K

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Tuple Fields§

    §0: K

    Trait Implementations§

    Build the complete descriptor

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    Convert to wallet descriptor
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Convert to wallet descriptor
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html index 70b22c9a4a..f135bba607 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html @@ -1,5 +1,4 @@ -DescriptorTemplate in bdk::descriptor::template - Rust
    pub trait DescriptorTemplate {
    +DescriptorTemplate in bdk::descriptor::template - Rust
    pub trait DescriptorTemplate {
         fn build(
            self,
            network: Network
        ) -> Result<DescriptorTemplateOut, DescriptorError>; }
    Expand description

    Trait for descriptor templates that can be built into a full descriptor

    Since IntoWalletDescriptor is implemented for any DescriptorTemplate, they can also be @@ -19,4 +18,4 @@ passed directly to the Wallet

    Required Methods§

    Build the complete descriptor

    -

    Implementors§

    \ No newline at end of file +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html index 7579f1d4f2..d45b0069f4 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html @@ -1,3 +1,2 @@ -DescriptorTemplateOut in bdk::descriptor::template - Rust

    Type Definition bdk::descriptor::template::DescriptorTemplateOut

    source ·
    pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);
    Expand description

    Type alias for the return type of DescriptorTemplate, descriptor! and others

    -

    Trait Implementations§

    Convert to wallet descriptor
    \ No newline at end of file +DescriptorTemplateOut in bdk::descriptor::template - Rust

    Type Definition bdk::descriptor::template::DescriptorTemplateOut

    source ·
    pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);
    Expand description

    Type alias for the return type of DescriptorTemplate, descriptor! and others

    +

    Trait Implementations§

    Convert to wallet descriptor
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html index ec97aef363..d8cc898558 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html @@ -1,6 +1,5 @@ -ExtractPolicy in bdk::descriptor - Rust
    pub trait ExtractPolicy {
    +ExtractPolicy in bdk::descriptor - Rust
    pub trait ExtractPolicy {
         fn extract_policy(
            &self,
            signers: &SignersContainer,
            psbt: BuildSatisfaction<'_>,
            secp: &Secp256k1<All>
        ) -> Result<Option<Policy>, DescriptorError>; }
    Expand description

    Trait implemented on Descriptors to add a method to extract the spending policy

    -

    Required Methods§

    Extract the spending policy

    -

    Implementors§

    \ No newline at end of file +

    Required Methods§

    Extract the spending policy

    +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html index b977dea5fb..6db491ed85 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html @@ -1,8 +1,7 @@ -IntoWalletDescriptor in bdk::descriptor - Rust
    pub trait IntoWalletDescriptor {
    +IntoWalletDescriptor in bdk::descriptor - Rust
    pub trait IntoWalletDescriptor {
         fn into_wallet_descriptor(
            self,
            secp: &Secp256k1<All>,
            network: Network
        ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError>; }
    Expand description

    Trait for types which can be converted into an ExtendedDescriptor and a KeyMap usable by a wallet in a specific [Network]

    -

    Required Methods§

    Convert to wallet descriptor

    -

    Implementations on Foreign Types§

    Implementors§

    Turns a DescriptorTemplate into a valid wallet descriptor by calling its +

    Required Methods§

    Convert to wallet descriptor

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html index aaaf313ffc..1d7b6b472d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html @@ -1,5 +1,4 @@ -ScriptContext in bdk::descriptor - Rust
    pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
    +ScriptContext in bdk::descriptor - Rust
    pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
         type Key: ParseableKey<Sha256 = Hash, Hash256 = Hash, Ripemd160 = Hash, Hash160 = Hash> + MiniscriptKey;
     
     
    Show 15 methods fn check_terminal_non_malleable<Pk>(
            _frag: &Terminal<Pk, Self>
        ) -> Result<(), ScriptContextError>
        where
            Pk: MiniscriptKey
    ; diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html index 8dbc048988..9eba7b9dec 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html @@ -1,3 +1,2 @@ -DerivedDescriptor in bdk::descriptor - Rust

    Type Definition bdk::descriptor::DerivedDescriptor

    source ·
    pub type DerivedDescriptor = Descriptor<DefiniteDescriptorKey>;
    Expand description

    Alias for a Descriptor that contains extended derived keys

    +DerivedDescriptor in bdk::descriptor - Rust

    Type Definition bdk::descriptor::DerivedDescriptor

    source ·
    pub type DerivedDescriptor = Descriptor<DefiniteDescriptorKey>;
    Expand description

    Alias for a Descriptor that contains extended derived keys

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html index 44cbbbf09c..39778bcba9 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html @@ -1,3 +1,2 @@ -ExtendedDescriptor in bdk::descriptor - Rust

    Type Definition bdk::descriptor::ExtendedDescriptor

    source ·
    pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
    Expand description

    Alias for a Descriptor that can contain extended keys using DescriptorPublicKey

    -

    Trait Implementations§

    Convert to wallet descriptor
    \ No newline at end of file +ExtendedDescriptor in bdk::descriptor - Rust

    Type Definition bdk::descriptor::ExtendedDescriptor

    source ·
    pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
    Expand description

    Alias for a Descriptor that can contain extended keys using DescriptorPublicKey

    +

    Trait Implementations§

    Convert to wallet descriptor
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html index 085e2f1167..946e8740fa 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html @@ -1,4 +1,3 @@ -HdKeyPaths in bdk::descriptor - Rust

    Type Definition bdk::descriptor::HdKeyPaths

    source ·
    pub type HdKeyPaths = BTreeMap<PublicKey, KeySource>;
    Expand description

    Alias for the type of maps that represent derivation paths in a psbt::Input or +HdKeyPaths in bdk::descriptor - Rust

    Type Definition bdk::descriptor::HdKeyPaths

    source ·
    pub type HdKeyPaths = BTreeMap<PublicKey, KeySource>;
    Expand description

    Alias for the type of maps that represent derivation paths in a psbt::Input or psbt::Output

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.KeyMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.KeyMap.html index d4fbfda5ca..67ed23ddaf 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.KeyMap.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.KeyMap.html @@ -1,5 +1,4 @@ -KeyMap in bdk::descriptor - Rust

    Type Definition bdk::descriptor::KeyMap

    Expand description

    Alias type for a map of public key to secret key

    +KeyMap in bdk::descriptor - Rust

    Type Definition bdk::descriptor::KeyMap

    Expand description

    Alias type for a map of public key to secret key

    This map is returned whenever a descriptor that contains secrets is parsed using Descriptor::parse_descriptor, since the descriptor will always only contain public keys. This map allows looking up the corresponding secret key given a diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.TapKeyOrigins.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.TapKeyOrigins.html index 1a142aa271..482b3e59ee 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.TapKeyOrigins.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.TapKeyOrigins.html @@ -1,4 +1,3 @@ -TapKeyOrigins in bdk::descriptor - Rust

    Type Definition bdk::descriptor::TapKeyOrigins

    source ·
    pub type TapKeyOrigins = BTreeMap<XOnlyPublicKey, (Vec<TapLeafHash>, KeySource)>;
    Expand description

    Alias for the type of maps that represent taproot key origins in a psbt::Input or +TapKeyOrigins in bdk::descriptor - Rust

    Type Definition bdk::descriptor::TapKeyOrigins

    source ·
    pub type TapKeyOrigins = BTreeMap<XOnlyPublicKey, (Vec<TapLeafHash>, KeySource)>;
    Expand description

    Alias for the type of maps that represent taproot key origins in a psbt::Input or psbt::Output

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Error.html index ee2768de38..b5ee6f8614 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Error.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Error.html @@ -1,8 +1,5 @@ -Error in bdk - Rust

    Enum bdk::Error

    source ·
    pub enum Error {
    -
    Show 44 variants InvalidU32Bytes(Vec<u8>), - Generic(String), - ScriptDoesntHaveAddressForm, +Error in bdk - Rust

    Enum bdk::Error

    source ·
    pub enum Error {
    +
    Show 26 variants Generic(String), NoRecipients, NoUtxosSelected, OutputBelowDustLimit(usize), @@ -29,35 +26,14 @@ SpendingPolicyRequired(KeychainKind), InvalidPolicyPathError(PolicyError), Signer(SignerError), - InvalidNetwork { - requested: Network, - found: Network, - }, - Verification(VerifyError), - InvalidProgressValue(f32), - ProgressUpdateError, InvalidOutpoint(OutPoint), Descriptor(Error), - Encode(Error), Miniscript(Error), MiniscriptPsbt(MiniscriptPsbtError), Bip32(Error), - Secp256k1(Error), - Json(Error), - Hex(Error), Psbt(Error), - PsbtParse(PsbtParseError), - MissingCachedScripts(MissingCachedScripts), - Electrum(Error), - Esplora(Box<EsploraError>), - CompactFilters(CompactFiltersError), - Sled(Error), - Rpc(Error), - Rusqlite(Error),
    }
    Expand description

    Errors that can be thrown by the Wallet

    -

    Variants§

    §

    InvalidU32Bytes(Vec<u8>)

    Wrong number of bytes found when trying to convert to u32

    -
    §

    Generic(String)

    Generic error

    -
    §

    ScriptDoesntHaveAddressForm

    This error is thrown when trying to convert Bare and Public key script to address

    +

    Variants§

    §

    Generic(String)

    Generic error

    §

    NoRecipients

    Cannot build a tx without recipients

    §

    NoUtxosSelected

    manually_selected_only option is selected but no utxo has been passed

    §

    OutputBelowDustLimit(usize)

    Output created is under the dust limit, 546 satoshis

    @@ -85,34 +61,15 @@ explicit origin provided

    §

    SpendingPolicyRequired(KeychainKind)

    Spending policy is not compatible with this KeychainKind

    §

    InvalidPolicyPathError(PolicyError)

    Error while extracting and manipulating policies

    §

    Signer(SignerError)

    Signing error

    -
    §

    InvalidNetwork

    Fields

    §requested: Network

    requested network, for example what is given as bdk-cli option

    -
    §found: Network

    found network, for example the network of the bitcoin node

    -

    Invalid network

    -
    §

    Verification(VerifyError)

    Transaction verification error

    -
    §

    InvalidProgressValue(f32)

    Progress value must be between 0.0 (included) and 100.0 (included)

    -
    §

    ProgressUpdateError

    Progress update error (maybe the channel has been closed)

    §

    InvalidOutpoint(OutPoint)

    Requested outpoint doesn’t exist in the tx (vout greater than available outputs)

    §

    Descriptor(Error)

    Error related to the parsing and usage of descriptors

    -
    §

    Encode(Error)

    Encoding error

    §

    Miniscript(Error)

    Miniscript error

    §

    MiniscriptPsbt(MiniscriptPsbtError)

    Miniscript PSBT error

    §

    Bip32(Error)

    BIP32 error

    -
    §

    Secp256k1(Error)

    A secp256k1 error

    -
    §

    Json(Error)

    Error serializing or deserializing JSON data

    -
    §

    Hex(Error)

    Hex decoding error

    §

    Psbt(Error)

    Partially signed bitcoin transaction error

    -
    §

    PsbtParse(PsbtParseError)

    Partially signed bitcoin transaction parse error

    -
    §

    MissingCachedScripts(MissingCachedScripts)

    crate::blockchain::WalletSync sync attempt failed due to missing scripts in cache which -are needed to satisfy stop_gap.

    -
    §

    Electrum(Error)

    Electrum client error

    -
    §

    Esplora(Box<EsploraError>)

    Esplora client error

    -
    §

    CompactFilters(CompactFiltersError)

    Compact filters client error)

    -
    §

    Sled(Error)

    Sled database error

    -
    §

    Rpc(Error)

    Rpc client error

    -
    §

    Rusqlite(Error)

    Rusqlite client error

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to provide by using demand. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html index 9c8fd2372f..ce67a148c3 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html @@ -1,16 +1,17 @@ -KeychainKind in bdk - Rust

    Enum bdk::KeychainKind

    source ·
    pub enum KeychainKind {
    +KeychainKind in bdk - Rust

    Enum bdk::KeychainKind

    source ·
    pub enum KeychainKind {
         External,
         Internal,
     }
    Expand description

    Types of keychains

    Variants§

    §

    External

    External

    §

    Internal

    Internal, usually used for change outputs

    -

    Implementations§

    Return KeychainKind as a byte

    -

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method tests for self and other values to be equal, and is used +

    Implementations§

    Return KeychainKind as a byte

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Calculate the base32 serialized length
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more
    Error type if conversion fails
    Check if all values are in range and return array-like struct of u5 values

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Calculate the base32 serialized length
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more
    Error type if conversion fails
    Check if all values are in range and return array-like struct of u5 values

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    Encode as base32 and write it to the supplied writer -Implementations shouldn’t allocate. Read more
    Convert Self to base32 vector
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Encode as base32 and write it to the supplied writer +Implementations shouldn’t allocate. Read more
    Convert Self to base32 vector
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html index 77381f247e..f23b28f366 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html @@ -1,5 +1,4 @@ -Utxo in bdk - Rust

    Enum bdk::Utxo

    source ·
    pub enum Utxo {
    +Utxo in bdk - Rust

    Enum bdk::Utxo

    source ·
    pub enum Utxo {
         Local(LocalUtxo),
         Foreign {
             outpoint: OutPoint,
    @@ -10,12 +9,12 @@
     
    §

    Foreign

    Fields

    §outpoint: OutPoint

    The location of the output.

    §psbt_input: Box<Input>

    The information about the input we require to add it to a PSBT.

    A UTXO owned by another wallet.

    -

    Implementations§

    Get the location of the UTXO

    -

    Get the TxOut of the UTXO

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +

    Implementations§

    Get the location of the UTXO

    +

    Get the TxOut of the UTXO

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/fn.version.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/fn.version.html index fc1da06f07..a608f65d6d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/fn.version.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/fn.version.html @@ -1,3 +1,2 @@ -version in bdk - Rust

    Function bdk::version

    source ·
    pub fn version() -> &'static str
    Expand description

    Get the version of BDK at runtime

    +version in bdk - Rust

    Function bdk::version

    source ·
    pub fn version() -> &'static str
    Expand description

    Get the version of BDK at runtime

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/index.html index 98a92b0ec8..10afaa98ac 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/index.html @@ -1,144 +1,169 @@ -bdk - Rust

    Crate bdk

    source ·
    Expand description

    A modern, lightweight, descriptor-based wallet library written in Rust.

    -

    About

    -

    The BDK library aims to be the core building block for Bitcoin wallets of any kind.

    +bdk - Rust

    Crate bdk

    source ·
    Expand description
    +

    BDK

    + +

    + A modern, lightweight, descriptor-based wallet library written in Rust! +

    +

    + Crate Info + MIT or Apache-2.0 Licensed + CI Status + + API Docs + Rustc Version 1.57.0+ + Chat on Discord +

    +

    + Project Homepage + | + Documentation +

    +
    +

    bdk

    +

    The bdk crate provides the Wallet type which is a simple, high-level +interface built from the low-level components of bdk_chain. Wallet is a good starting point +for many simple applications as well as a good demonstration of how to use the other mechanisms to +construct a wallet. It has two keychains (external and internal) which are defined by +miniscript descriptors and uses them to generate addresses. When you give it +chain data it also uses the descriptors to find transaction outputs owned by them. From there, you +can create and sign transactions.

    +

    For more information, see the Wallet’s documentation.

    +

    Blockchain data

    +

    In order to get blockchain data for Wallet to consume, you have to put it into particular form. +Right now this is KeychainScan which is defined in bdk_chain.

    +

    This can be created manually or from blockchain-scanning crates.

    +

    Blockchain Data Sources

      -
    • It uses Miniscript to support descriptors with generalized conditions. This exact same library can be used to build -single-sig wallets, multisigs, timelocked contracts and more.
    • -
    • It supports multiple blockchain backends and databases, allowing developers to choose exactly what’s right for their projects.
    • -
    • It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
    • -
    • It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
    • +
    • bdk_esplora: Grabs blockchain data from Esplora for updating BDK structures.
    • +
    • bdk_electrum: Grabs blockchain data from Electrum for updating BDK structures.
    -

    A Tour of BDK

    -

    BDK consists of a number of modules that provide a range of functionality -essential for implementing descriptor based Bitcoin wallet applications in Rust. In this -section, we will take a brief tour of BDK, summarizing the major APIs and -their uses.

    -

    The easiest way to get started is to add bdk to your dependencies with the default features. -The default features include a simple key-value database (sled) to cache -blockchain data and an electrum blockchain client to -interact with the bitcoin P2P network.

    -

    Examples

    Sync the balance of a descriptor

    -
    use bdk::{Wallet, SyncOptions};
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::ElectrumBlockchain;
    -use bdk::electrum_client::Client;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -    let blockchain = ElectrumBlockchain::from(client);
    -    let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -    )?;
    -
    -    wallet.sync(&blockchain, SyncOptions::default())?;
    -
    -    println!("Descriptor balance: {} SAT", wallet.get_balance()?);
    -
    -    Ok(())
    -}
    -

    Generate a few addresses

    Example

    -
    use bdk::{Wallet};
    -use bdk::database::MemoryDatabase;
    -use bdk::wallet::AddressIndex::New;
    -
    -fn main() -> Result<(), bdk::Error> {
    -let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -    )?;
    -
    -    println!("Address #0: {}", wallet.get_address(New)?);
    -    println!("Address #1: {}", wallet.get_address(New)?);
    -    println!("Address #2: {}", wallet.get_address(New)?);
    -
    -    Ok(())
    -}
    -

    Create a transaction

    -
    use bdk::{FeeRate, Wallet, SyncOptions};
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::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(),
    -    )?;
    -    let blockchain = ElectrumBlockchain::from(client);
    -
    -    wallet.sync(&blockchain, SyncOptions::default())?;
    -
    -    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: {}", &psbt);
    -
    -    Ok(())
    -}
    -

    Sign a transaction

    -
    use std::str::FromStr;
    -
    -use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
    -
    -use bdk::{Wallet, SignOptions};
    -use bdk::database::MemoryDatabase;
    +

    Examples

    + +

    Persistence

    +

    To persist the Wallet on disk, Wallet needs to be constructed with a +Persist implementation.

    +

    Implementations

    + +

    Example

    -fn main() -> Result<(), bdk::Error> { - let wallet = Wallet::new( - "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)", - Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"), - bitcoin::Network::Testnet, - MemoryDatabase::default(), - )?; +
    use bdk::{bitcoin::Network, wallet::{AddressIndex, Wallet}};
     
    -    let psbt = "...";
    -    let mut psbt = Psbt::from_str(psbt)?;
    +fn main() {
    +    // a type that implements `Persist`
    +    let db = ();
     
    -    let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    +    let descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)";
    +    let mut wallet = Wallet::new(descriptor, None, db, Network::Testnet).expect("should create");
     
    -    Ok(())
    +    // get a new address (this increments revealed derivation index)
    +    println!("revealed address: {}", wallet.get_address(AddressIndex::New));
    +    println!("staged changes: {:?}", wallet.staged());
    +    // persist changes
    +    wallet.commit().expect("must save");
     }
    -

    Feature flags

    -

    BDK uses a set of feature flags -to reduce the amount of compiled code by allowing projects to only enable the features they need. -By default, BDK enables two internal features, key-value-db and electrum.

    -

    If you are new to BDK we recommended that you use the default features which will enable -basic descriptor wallet functionality. More advanced users can disable the default features -(--no-default-features) and build the BDK library with only the features you need. -Below is a list of the available feature flags and the additional functionality they provide.

    -
      -
    • all-keys: all features for working with bitcoin keys
    • -
    • async-interface: async functions in bdk traits
    • -
    • keys-bip39: BIP-39 mnemonic codes for generating deterministic keys
    • -
    -

    Internal features

    -

    These features do not expose any new API, but influence internal implementation aspects of -BDK.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Testing

    Unit testing

    cargo test
    +

    License

    +

    Licensed under either of

    -

    Re-exports

    pub extern crate bitcoin;
    pub extern crate bitcoincore_rpc;
    pub extern crate electrum_client;
    pub extern crate esplora_client;
    pub extern crate hwi;
    pub extern crate miniscript;
    pub extern crate rusqlite;
    pub extern crate sled;
    pub use descriptor::template;
    pub use descriptor::HdKeyPaths;
    pub use wallet::signer;
    pub use wallet::signer::SignOptions;
    pub use wallet::tx_builder::TxBuilder;
    pub use wallet::SyncOptions;
    pub use wallet::Wallet;

    Modules

    Blockchain backends
    Database types
    Descriptors
    Key formats
    Additional functions on the rust-bitcoin PartiallySignedTransaction structure.
    Wallet

    Macros

    Macro to write full descriptors with code
    Macro to write descriptor fragments with code

    Structs

    Balance differentiated in various categories
    Block height and timestamp of a block
    Fee rate
    An unspent output owned by a Wallet.
    A wallet transaction
    A Utxo with its satisfaction_weight.

    Enums

    Errors that can be thrown by the Wallet
    Types of keychains
    An unspent transaction output (UTXO).

    Traits

    Trait implemented by types that can be used to measure weight units.

    Functions

    Get the version of BDK at runtime

    Type Definitions

    DEPRECATED: Confirmation time of a transaction
    \ No newline at end of file +

    at your option.

    +

    Contribution

    +

    Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions.

    +

    Re-exports

    pub extern crate bitcoin;
    pub extern crate miniscript;
    pub use descriptor::template;
    pub use descriptor::HdKeyPaths;
    pub use wallet::signer;
    pub use wallet::signer::SignOptions;
    pub use wallet::tx_builder::TxBuilder;
    pub use wallet::Wallet;
    pub use bdk_chain as chain;

    Modules

    Descriptors
    Key formats
    Additional functions on the rust-bitcoin PartiallySignedTransaction structure.
    Wallet

    Macros

    Macro to write full descriptors with code
    Macro to write descriptor fragments with code

    Structs

    Fee rate
    An unspent output owned by a Wallet.
    A wallet transaction
    A Utxo with its satisfaction_weight.

    Enums

    Errors that can be thrown by the Wallet
    Types of keychains
    An unspent transaction output (UTXO).

    Traits

    Trait implemented by types that can be used to measure weight units.

    Functions

    Get the version of BDK at runtime
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Error.html deleted file mode 100644 index bae2a50aa4..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Error.html +++ /dev/null @@ -1,25 +0,0 @@ -Error in bdk::keys::bip39 - Rust

    Enum bdk::keys::bip39::Error

    pub enum Error {
    -    BadWordCount(usize),
    -    UnknownWord(usize),
    -    BadEntropyBitCount(usize),
    -    InvalidChecksum,
    -    AmbiguousLanguages(AmbiguousLanguages),
    -}
    Available on crate feature keys-bip39 only.
    Expand description

    A BIP39 error.

    -

    Variants§

    §

    BadWordCount(usize)

    Mnemonic has a word count that is not a multiple of 6.

    -
    §

    UnknownWord(usize)

    Mnemonic contains an unknown word. -Error contains the index of the word. -Use mnemonic.split_whitespace().get(i) to get the word.

    -
    §

    BadEntropyBitCount(usize)

    Entropy was not a multiple of 32 bits or between 128-256n bits in length.

    -
    §

    InvalidChecksum

    The mnemonic has an invalid checksum.

    -
    §

    AmbiguousLanguages(AmbiguousLanguages)

    The mnemonic can be interpreted as multiple languages. -Use the helper methods of the inner struct to inspect -which languages are possible.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    This method tests for self and other values to be equal, and is used -by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to -provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html deleted file mode 100644 index 93653e43cc..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html +++ /dev/null @@ -1,21 +0,0 @@ -Language in bdk::keys::bip39 - Rust

    Enum bdk::keys::bip39::Language

    pub enum Language {
    -    English,
    -}
    Available on crate feature keys-bip39 only.
    Expand description

    Language to be used for the mnemonic phrase.

    -

    The English language is always available, other languages are enabled using -the compilation features.

    -

    Variants§

    §

    English

    The English language.

    -

    Implementations§

    The list of supported languages. -Language support is managed by compile features.

    -

    The word list for this language.

    -

    Get words from the word list that start with the given prefix.

    -

    Get the index of the word in the word list.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Formats the value using the given formatter. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used -by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= -operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.WordCount.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.WordCount.html deleted file mode 100644 index a60c995654..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.WordCount.html +++ /dev/null @@ -1,18 +0,0 @@ -WordCount in bdk::keys::bip39 - Rust

    Enum bdk::keys::bip39::WordCount

    source ·
    pub enum WordCount {
    -    Words12,
    -    Words15,
    -    Words18,
    -    Words21,
    -    Words24,
    -}
    Available on crate feature keys-bip39 only.
    Expand description

    Type describing entropy length (aka word count) in the mnemonic

    -

    Variants§

    §

    Words12

    12 words mnemonic (128 bits entropy)

    -
    §

    Words15

    15 words mnemonic (160 bits entropy)

    -
    §

    Words18

    18 words mnemonic (192 bits entropy)

    -
    §

    Words21

    21 words mnemonic (224 bits entropy)

    -
    §

    Words24

    24 words mnemonic (256 bits entropy)

    -

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html deleted file mode 100644 index 8e736b08f9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html +++ /dev/null @@ -1,3 +0,0 @@ -bdk::keys::bip39 - Rust

    Module bdk::keys::bip39

    source ·
    Available on crate feature keys-bip39 only.
    Expand description

    BIP-0039

    -

    Structs

    A mnemonic code.

    Enums

    A BIP39 error.
    Language to be used for the mnemonic phrase.
    Type describing entropy length (aka word count) in the mnemonic

    Type Definitions

    Type for a BIP39 mnemonic with an optional passphrase
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js deleted file mode 100644 index 0ed5efca1c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["Error","A BIP39 error."],["Language","Language to be used for the mnemonic phrase."],["WordCount","Type describing entropy length (aka word count) in the mnemonic"]],"struct":[["Mnemonic","A mnemonic code."]],"type":[["MnemonicWithPassphrase","Type for a BIP39 mnemonic with an optional passphrase"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html deleted file mode 100644 index 1a3ac4b7fc..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html +++ /dev/null @@ -1,53 +0,0 @@ -Mnemonic in bdk::keys::bip39 - Rust

    Struct bdk::keys::bip39::Mnemonic

    pub struct Mnemonic { /* private fields */ }
    Available on crate feature keys-bip39 only.
    Expand description

    A mnemonic code.

    -

    The core::str::FromStr implementation will try to determine the language of the -mnemonic from all the supported languages. (Languages have to be explicitly enabled using -the Cargo features.)

    -

    Supported number of words are 12, 15, 18, 21, and 24.

    -

    Implementations§

    Create a new Mnemonic in the specified language from the given entropy. -Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.

    -

    Create a new English Mnemonic from the given entropy. -Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.

    -

    Generate a new Mnemonic in the given language -with the given randomness source. -For the different supported word counts, see documentation on Mnemonic.

    -

    Example:

    - -
    extern crate rand;
    -extern crate bip39;
    -
    -use bip39::{Mnemonic, Language};
    -
    -let mut rng = rand::thread_rng();
    -let m = Mnemonic::generate_in_with(&mut rng, Language::English, 24).unwrap();
    -

    Get the language of the Mnemonic.

    -

    Get an iterator over the words.

    -

    Determine the language of the mnemonic.

    -

    NOTE: This method only guarantees that the returned language is the -correct language on the assumption that the mnemonic is valid. -It does not itself validate the mnemonic.

    -

    Some word lists don’t guarantee that their words don’t occur in other -word lists. In the extremely unlikely case that a word list can be -interpreted in multiple languages, an Error::AmbiguousLanguages is -returned, containing the possible languages.

    -

    Parse a mnemonic in normalized UTF8 in the given language.

    -

    Parse a mnemonic in normalized UTF8.

    -

    Parse a mnemonic in the given language.

    -

    Parse a mnemonic and detect the language from the enabled languages.

    -

    Get the number of words in the mnemonic.

    -

    Convert to seed bytes with a passphrase in normalized UTF8.

    -

    Convert to seed bytes.

    -

    Convert the mnemonic back to the entropy used to generate it. -The return value is a byte array and the size. -Use Mnemonic::to_entropy (needs std) to get a Vec.

    -

    Convert the mnemonic back to the entropy used to generate it.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Consume self and turn it into an ExtendedKey Read more
    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more
    Type specifying the amount of entropy required e.g. [u8;32]
    Extra options required by the generate_with_entropy
    Returned error in case of failure
    Generate a key given the extra options and the entropy
    Generate a key given the options with a random entropy
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used -by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= -operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html deleted file mode 100644 index 7dc19c6f7a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html +++ /dev/null @@ -1,4 +0,0 @@ -MnemonicWithPassphrase in bdk::keys::bip39 - Rust

    Type Definition bdk::keys::bip39::MnemonicWithPassphrase

    source ·
    pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
    Available on crate feature keys-bip39 only.
    Expand description

    Type for a BIP39 mnemonic with an optional passphrase

    -

    Trait Implementations§

    Consume self and turn it into an ExtendedKey Read more
    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html index 54bcc3be88..c75e8ffbca 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html @@ -1,13 +1,12 @@ -DescriptorKey in bdk::keys - Rust

    Enum bdk::keys::DescriptorKey

    source ·
    pub enum DescriptorKey<Ctx: ScriptContext> {
    +DescriptorKey in bdk::keys - Rust

    Enum bdk::keys::DescriptorKey

    source ·
    pub enum DescriptorKey<Ctx: ScriptContext> {
         // some variants omitted
     }
    Expand description

    Container for public or secret keys

    -

    Implementations§

    Create an instance given a public key and a set of valid networks

    -

    Create an instance given a secret key and a set of valid networks

    -

    Override the computed set of valid networks

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more

    The “identity” conversion is used internally by some bdk::fragments

    -
    Turn the key into a DescriptorKey within the requested ScriptContext

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Implementations§

    Create an instance given a public key and a set of valid networks

    +

    Create an instance given a secret key and a set of valid networks

    +

    Override the computed set of valid networks

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more

    The “identity” conversion is used internally by some bdk::fragments

    +
    Turn the key into a DescriptorKey within the requested ScriptContext

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html index 52f0326710..34b751e60c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html @@ -1,5 +1,4 @@ -DescriptorPublicKey in bdk::keys - Rust

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    Converts to this type from the input type.
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    Turn the key into a DescriptorKey within the requested ScriptContext
    The associated [sha256::Hash] for this [MiniscriptKey], +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    Converts to this type from the input type.
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    Turn the key into a DescriptorKey within the requested ScriptContext
    The associated [sha256::Hash] for this [MiniscriptKey], used in the hash256 fragment. Read more
    The associated [hash256::Hash] for this [MiniscriptKey], used in the hash256 fragment. Read more
    The associated [ripedmd160::Hash] for this [MiniscriptKey] type. used in the ripemd160 fragment Read more
    The associated [hash160::Hash] for this [MiniscriptKey] type. @@ -31,8 +30,8 @@ used in the hash160 fragment Read more
    Read more
    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html index 432492ccc7..9e7c2ee475 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html @@ -1,5 +1,4 @@ -DescriptorSecretKey in bdk::keys - Rust
    pub enum DescriptorSecretKey {
    +DescriptorSecretKey in bdk::keys - Rust
    pub enum DescriptorSecretKey {
         Single(SinglePriv),
         XPrv(DescriptorXKey<ExtendedPrivKey>),
     }
    Expand description

    The descriptor secret key, either a single private key or an xprv.

    @@ -8,8 +7,8 @@

    Implementations§

    Returns the public version of this key.

    If the key is an “XPrv”, the hardened derivation steps will be applied before converting it to a public key.

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more
    Turn the key into a DescriptorKey within the requested ScriptContext

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more
    Turn the key into a DescriptorKey within the requested ScriptContext

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html index 244c0d58c8..d57223406d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html @@ -1,5 +1,4 @@ -ExtendedKey in bdk::keys - Rust

    Enum bdk::keys::ExtendedKey

    source ·
    pub enum ExtendedKey<Ctx: ScriptContext = Legacy> {
    +ExtendedKey in bdk::keys - Rust

    Enum bdk::keys::ExtendedKey

    source ·
    pub enum ExtendedKey<Ctx: ScriptContext = Legacy> {
         Private((ExtendedPrivKey, PhantomData<Ctx>)),
         Public((ExtendedPubKey, PhantomData<Ctx>)),
     }
    Expand description

    Enum for extended keys that can be either xprv or xpub

    @@ -8,15 +7,15 @@ or an ExtendedPubKey by using t

    Defaults to the Legacy context.

    Variants§

    §

    Private((ExtendedPrivKey, PhantomData<Ctx>))

    A private extended key, aka an xprv

    §

    Public((ExtendedPubKey, PhantomData<Ctx>))

    A public extended key, aka an xpub

    -

    Implementations§

    Return whether or not the key contains the private data

    -

    Transform the ExtendedKey into an ExtendedPrivKey for the +

    Implementations§

    Return whether or not the key contains the private data

    +

    Transform the ExtendedKey into an ExtendedPrivKey for the given [Network], if the key contains the private data

    -

    Transform the ExtendedKey into an ExtendedPubKey for the +

    Transform the ExtendedKey into an ExtendedPubKey for the given [Network]

    -

    Trait Implementations§

    Identity conversion

    -
    Consume self and turn it into an ExtendedKey Read more
    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Identity conversion

    +
    Consume self and turn it into an ExtendedKey
    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +key origin and derivation path Read more
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html index 1d09148fb7..2c30c81e73 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html @@ -1,5 +1,4 @@ -KeyError in bdk::keys - Rust

    Enum bdk::keys::KeyError

    source ·
    pub enum KeyError {
    +KeyError in bdk::keys - Rust

    Enum bdk::keys::KeyError

    source ·
    pub enum KeyError {
         InvalidScriptContext,
         InvalidNetwork,
         InvalidChecksum,
    @@ -13,9 +12,9 @@
     
    §

    Message(String)

    Custom error message

    §

    Bip32(Error)

    BIP32 error

    §

    Miniscript(Error)

    Miniscript error

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to provide by using demand. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html index cdd5ee8e6b..0aecd24f6e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html @@ -1,5 +1,4 @@ -ScriptContextEnum in bdk::keys - Rust

    Enum bdk::keys::ScriptContextEnum

    source ·
    pub enum ScriptContextEnum {
    +ScriptContextEnum in bdk::keys - Rust

    Enum bdk::keys::ScriptContextEnum

    source ·
    pub enum ScriptContextEnum {
         Legacy,
         Segwitv0,
         Tap,
    @@ -7,13 +6,13 @@
     

    Variants§

    §

    Legacy

    Legacy scripts

    §

    Segwitv0

    Segwitv0 scripts

    §

    Tap

    Taproot scripts

    -

    Implementations§

    Returns whether the script context is ScriptContextEnum::Legacy

    -

    Returns whether the script context is ScriptContextEnum::Segwitv0

    -

    Returns whether the script context is ScriptContextEnum::Tap

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +

    Implementations§

    Returns whether the script context is ScriptContextEnum::Legacy

    +

    Returns whether the script context is ScriptContextEnum::Segwitv0

    +

    Returns whether the script context is ScriptContextEnum::Tap

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.SinglePubKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.SinglePubKey.html index d42db77612..c4a4b7b59f 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.SinglePubKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.SinglePubKey.html @@ -1,5 +1,4 @@ -SinglePubKey in bdk::keys - Rust

    Enum bdk::keys::SinglePubKey

    pub enum SinglePubKey {
    +SinglePubKey in bdk::keys - Rust

    Enum bdk::keys::SinglePubKey

    pub enum SinglePubKey {
         FullKey(PublicKey),
         XOnly(XOnlyPublicKey),
     }
    Expand description

    Single public key without any origin or range information.

    @@ -9,8 +8,8 @@ by ==. Read more
    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html index 25df445c11..66662abd8a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html @@ -1,3 +1,2 @@ -any_network in bdk::keys - Rust

    Function bdk::keys::any_network

    source ·
    pub fn any_network() -> ValidNetworks
    Expand description

    Create a set containing mainnet, testnet, signet, and regtest

    +any_network in bdk::keys - Rust

    Function bdk::keys::any_network

    source ·
    pub fn any_network() -> ValidNetworks
    Expand description

    Create a set containing mainnet, testnet, signet, and regtest

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html index c7106b9a94..45e2a5298f 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html @@ -1,3 +1,2 @@ -mainnet_network in bdk::keys - Rust

    Function bdk::keys::mainnet_network

    source ·
    pub fn mainnet_network() -> ValidNetworks
    Expand description

    Create a set only containing mainnet

    +mainnet_network in bdk::keys - Rust

    Function bdk::keys::mainnet_network

    source ·
    pub fn mainnet_network() -> ValidNetworks
    Expand description

    Create a set only containing mainnet

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html index 6e4c1620d2..3e6078c67c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html @@ -1,3 +1,2 @@ -merge_networks in bdk::keys - Rust

    Function bdk::keys::merge_networks

    source ·
    pub fn merge_networks(a: &ValidNetworks, b: &ValidNetworks) -> ValidNetworks
    Expand description

    Compute the intersection of two sets

    +merge_networks in bdk::keys - Rust

    Function bdk::keys::merge_networks

    source ·
    pub fn merge_networks(a: &ValidNetworks, b: &ValidNetworks) -> ValidNetworks
    Expand description

    Compute the intersection of two sets

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html index 8fc6cf361d..4aea87ff77 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html @@ -1,3 +1,2 @@ -test_networks in bdk::keys - Rust

    Function bdk::keys::test_networks

    source ·
    pub fn test_networks() -> ValidNetworks
    Expand description

    Create a set containing testnet and regtest

    +test_networks in bdk::keys - Rust

    Function bdk::keys::test_networks

    source ·
    pub fn test_networks() -> ValidNetworks
    Expand description

    Create a set containing testnet and regtest

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/index.html index 2731f3e349..6219cdc233 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/index.html @@ -1,6 +1,5 @@ -bdk::keys - Rust

    Module bdk::keys

    source ·
    Expand description

    Key formats

    -

    Modules

    bip39keys-bip39
    BIP-0039

    Structs

    Output of a GeneratableKey key generation
    Options for generating a [PrivateKey]
    A descriptor [bitcoin::PrivateKey] with optional origin information.
    A descriptor SinglePubKey with optional origin information.
    Contents of a “sortedmulti” descriptor

    Enums

    Container for public or secret keys
    The descriptor pubkey, either a single pubkey or an xpub.
    The descriptor secret key, either a single private key or an xprv.
    Enum for extended keys that can be either xprv or xpub
    Errors thrown while working with keys
    Enum representation of the known valid ScriptContexts
    Single public key without any origin or range information.

    Traits

    Trait for keys that can be derived.
    Trait that adds extra useful methods to ScriptContexts
    Trait that allows generating a key with the default options
    Trait for keys that can be generated
    Trait for objects that can be turned into a public or secret DescriptorKey
    The ScriptContext for Miniscript. Additional type information associated with +bdk::keys - Rust

    Module bdk::keys

    source ·
    Expand description

    Key formats

    +

    Structs

    Output of a GeneratableKey key generation
    Options for generating a [PrivateKey]
    A descriptor [bitcoin::PrivateKey] with optional origin information.
    A descriptor SinglePubKey with optional origin information.
    Contents of a “sortedmulti” descriptor

    Enums

    Container for public or secret keys
    The descriptor pubkey, either a single pubkey or an xpub.
    The descriptor secret key, either a single private key or an xprv.
    Enum for extended keys that can be either xprv or xpub
    Errors thrown while working with keys
    Enum representation of the known valid ScriptContexts
    Single public key without any origin or range information.

    Traits

    Trait for keys that can be derived.
    Trait that adds extra useful methods to ScriptContexts
    Trait that allows generating a key with the default options
    Trait for keys that can be generated
    Trait for objects that can be turned into a public or secret DescriptorKey
    The ScriptContext for Miniscript. Additional type information associated with miniscript that is used for carrying out checks that dependent on the context under which the script is used. For example, disallowing uncompressed keys in Segwit context

    Functions

    Create a set containing mainnet, testnet, signet, and regtest
    Create a set only containing mainnet
    Compute the intersection of two sets
    Create a set containing testnet and regtest

    Type Definitions

    Alias type for a map of public key to secret key
    Set of valid networks for a key
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js index 7ccece3a39..bb1823d1c3 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"enum":[["DescriptorKey","Container for public or secret keys"],["DescriptorPublicKey","The descriptor pubkey, either a single pubkey or an xpub."],["DescriptorSecretKey","The descriptor secret key, either a single private key or an xprv."],["ExtendedKey","Enum for extended keys that can be either `xprv` or `xpub`"],["KeyError","Errors thrown while working with `keys`"],["ScriptContextEnum","Enum representation of the known valid [`ScriptContext`]s"],["SinglePubKey","Single public key without any origin or range information."]],"fn":[["any_network","Create a set containing mainnet, testnet, signet, and regtest"],["mainnet_network","Create a set only containing mainnet"],["merge_networks","Compute the intersection of two sets"],["test_networks","Create a set containing testnet and regtest"]],"mod":[["bip39","BIP-0039"]],"struct":[["GeneratedKey","Output of a [`GeneratableKey`] key generation"],["PrivateKeyGenerateOptions","Options for generating a [`PrivateKey`]"],["SinglePriv","A descriptor [`bitcoin::PrivateKey`] with optional origin information."],["SinglePub","A descriptor [`SinglePubKey`] with optional origin information."],["SortedMultiVec","Contents of a “sortedmulti” descriptor"]],"trait":[["DerivableKey","Trait for keys that can be derived."],["ExtScriptContext","Trait that adds extra useful methods to [`ScriptContext`]s"],["GeneratableDefaultOptions","Trait that allows generating a key with the default options"],["GeneratableKey","Trait for keys that can be generated"],["IntoDescriptorKey","Trait for objects that can be turned into a public or secret [`DescriptorKey`]"],["ScriptContext","The ScriptContext for Miniscript. Additional type information associated with miniscript that is used for carrying out checks that dependent on the context under which the script is used. For example, disallowing uncompressed keys in Segwit context"]],"type":[["KeyMap","Alias type for a map of public key to secret key"],["ValidNetworks","Set of valid networks for a key"]]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"enum":[["DescriptorKey","Container for public or secret keys"],["DescriptorPublicKey","The descriptor pubkey, either a single pubkey or an xpub."],["DescriptorSecretKey","The descriptor secret key, either a single private key or an xprv."],["ExtendedKey","Enum for extended keys that can be either `xprv` or `xpub`"],["KeyError","Errors thrown while working with `keys`"],["ScriptContextEnum","Enum representation of the known valid [`ScriptContext`]s"],["SinglePubKey","Single public key without any origin or range information."]],"fn":[["any_network","Create a set containing mainnet, testnet, signet, and regtest"],["mainnet_network","Create a set only containing mainnet"],["merge_networks","Compute the intersection of two sets"],["test_networks","Create a set containing testnet and regtest"]],"struct":[["GeneratedKey","Output of a [`GeneratableKey`] key generation"],["PrivateKeyGenerateOptions","Options for generating a [`PrivateKey`]"],["SinglePriv","A descriptor [`bitcoin::PrivateKey`] with optional origin information."],["SinglePub","A descriptor [`SinglePubKey`] with optional origin information."],["SortedMultiVec","Contents of a “sortedmulti” descriptor"]],"trait":[["DerivableKey","Trait for keys that can be derived."],["ExtScriptContext","Trait that adds extra useful methods to [`ScriptContext`]s"],["GeneratableDefaultOptions","Trait that allows generating a key with the default options"],["GeneratableKey","Trait for keys that can be generated"],["IntoDescriptorKey","Trait for objects that can be turned into a public or secret [`DescriptorKey`]"],["ScriptContext","The ScriptContext for Miniscript. Additional type information associated with miniscript that is used for carrying out checks that dependent on the context under which the script is used. For example, disallowing uncompressed keys in Segwit context"]],"type":[["KeyMap","Alias type for a map of public key to secret key"],["ValidNetworks","Set of valid networks for a key"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html index 361fee444a..e854799ea5 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html @@ -1,9 +1,8 @@ -GeneratedKey in bdk::keys - Rust

    Struct bdk::keys::GeneratedKey

    source ·
    pub struct GeneratedKey<K, Ctx: ScriptContext> { /* private fields */ }
    Expand description

    Output of a GeneratableKey key generation

    -

    Implementations§

    Consumes self and returns the key

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    The resulting type after dereferencing.
    Dereferences the value.
    Consume self and turn it into an ExtendedKey Read more
    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more
    Turn the key into a DescriptorKey within the requested ScriptContext

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +GeneratedKey in bdk::keys - Rust

    Struct bdk::keys::GeneratedKey

    source ·
    pub struct GeneratedKey<K, Ctx: ScriptContext> { /* private fields */ }
    Expand description

    Output of a GeneratableKey key generation

    +

    Implementations§

    Consumes self and returns the key

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    The resulting type after dereferencing.
    Dereferences the value.
    Consume self and turn it into an ExtendedKey
    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +key origin and derivation path Read more
    Turn the key into a DescriptorKey within the requested ScriptContext

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html index 3b20437518..8a21aa654d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html @@ -1,11 +1,10 @@ -PrivateKeyGenerateOptions in bdk::keys - Rust
    pub struct PrivateKeyGenerateOptions {
    +PrivateKeyGenerateOptions in bdk::keys - Rust
    pub struct PrivateKeyGenerateOptions {
         pub compressed: bool,
     }
    Expand description

    Options for generating a [PrivateKey]

    Defaults to creating compressed keys, which save on-chain bytes and fees

    Fields§

    §compressed: bool

    Whether the generated key should be “compressed” or not

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePriv.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePriv.html index 087eacb400..0c6ee6cb3b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePriv.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePriv.html @@ -1,5 +1,4 @@ -SinglePriv in bdk::keys - Rust

    Struct bdk::keys::SinglePriv

    pub struct SinglePriv {
    +SinglePriv in bdk::keys - Rust

    Struct bdk::keys::SinglePriv

    pub struct SinglePriv {
         pub origin: Option<(Fingerprint, DerivationPath)>,
         pub key: PrivateKey,
     }
    Expand description

    A descriptor [bitcoin::PrivateKey] with optional origin information.

    @@ -9,4 +8,4 @@

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePub.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePub.html index effbffa9c9..ec63bce007 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePub.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePub.html @@ -1,5 +1,4 @@ -SinglePub in bdk::keys - Rust

    Struct bdk::keys::SinglePub

    pub struct SinglePub {
    +SinglePub in bdk::keys - Rust

    Struct bdk::keys::SinglePub

    pub struct SinglePub {
         pub origin: Option<(Fingerprint, DerivationPath)>,
         pub key: SinglePubKey,
     }
    Expand description

    A descriptor SinglePubKey with optional origin information.

    @@ -9,8 +8,8 @@ by ==. Read more
    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html index f25500a420..218cb1197b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html @@ -1,5 +1,4 @@ -SortedMultiVec in bdk::keys - Rust

    Struct bdk::keys::SortedMultiVec

    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html index 1900a15ebc..d27926fd39 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html @@ -1,5 +1,4 @@ -DerivableKey in bdk::keys - Rust

    Trait bdk::keys::DerivableKey

    source ·
    pub trait DerivableKey<Ctx: ScriptContext = Legacy>: Sized {
    +DerivableKey in bdk::keys - Rust

    Trait bdk::keys::DerivableKey

    source ·
    pub trait DerivableKey<Ctx: ScriptContext = Legacy>: Sized {
         fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError>;
     
         fn into_descriptor_key(
            self,
            origin: Option<KeySource>,
            derivation_path: DerivationPath
        ) -> Result<DescriptorKey<Ctx>, KeyError> { ... } @@ -81,22 +80,8 @@ steps to override the set of valid networks, otherwise only the network specifie Ok(descriptor_key.override_valid_networks(any_network())) } }
    -

    Required Methods§

    Consume self and turn it into an ExtendedKey

    -

    This can be used to get direct access to xprvs and xpubs for types that implement this trait, -like Mnemonic when the keys-bip39 feature is enabled.

    - -
    use bdk::bitcoin::Network;
    -use bdk::keys::{DerivableKey, ExtendedKey};
    -use bdk::keys::bip39::{Mnemonic, Language};
    -
    -let xkey: ExtendedKey =
    -    Mnemonic::parse_in(
    -        Language::English,
    -        "jelly crash boy whisper mouse ecology tuna soccer memory million news short",
    -    )?
    -    .into_extended_key()?;
    -let xprv = xkey.into_xprv(Network::Bitcoin).unwrap();
    -

    Provided Methods§

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +

    Required Methods§

    Consume self and turn it into an ExtendedKey

    +

    Provided Methods§

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as key origin and derivation path

    -

    Implementations on Foreign Types§

    Implementors§

    Identity conversion

    -
    \ No newline at end of file +

    Implementations on Foreign Types§

    Implementors§

    Identity conversion

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html index f9d1ecc137..419f0f9043 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html @@ -1,13 +1,12 @@ -ExtScriptContext in bdk::keys - Rust

    Trait bdk::keys::ExtScriptContext

    source ·
    pub trait ExtScriptContext: ScriptContext {
    +ExtScriptContext in bdk::keys - Rust

    Trait bdk::keys::ExtScriptContext

    source ·
    pub trait ExtScriptContext: ScriptContext {
         fn as_enum() -> ScriptContextEnum;
     
         fn is_legacy() -> bool { ... }
         fn is_segwit_v0() -> bool { ... }
         fn is_taproot() -> bool { ... }
     }
    Expand description

    Trait that adds extra useful methods to ScriptContexts

    -

    Required Methods§

    Provided Methods§

    Returns whether the script context is Legacy

    -

    Returns whether the script context is Segwitv0

    -

    Returns whether the script context is Tap, aka Taproot or Segwit V1

    -

    Implementors§

    \ No newline at end of file +

    Required Methods§

    Provided Methods§

    Returns whether the script context is Legacy

    +

    Returns whether the script context is Segwitv0

    +

    Returns whether the script context is Tap, aka Taproot or Segwit V1

    +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html index 12fc760a21..b65c7d2300 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html @@ -1,11 +1,10 @@ -GeneratableDefaultOptions in bdk::keys - Rust
    pub trait GeneratableDefaultOptions<Ctx>: GeneratableKey<Ctx>where
        Ctx: ScriptContext,
        <Self as GeneratableKey<Ctx>>::Options: Default,
    { +GeneratableDefaultOptions in bdk::keys - Rust
    pub trait GeneratableDefaultOptions<Ctx>: GeneratableKey<Ctx>where
        Ctx: ScriptContext,
        <Self as GeneratableKey<Ctx>>::Options: Default,
    { fn generate_with_entropy_default(
            entropy: Self::Entropy
        ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } }
    Expand description

    Trait that allows generating a key with the default options

    This trait is automatically implemented if the GeneratableKey::Options implements Default.

    -

    Provided Methods§

    Generate a key with the default options and a given entropy

    -

    Generate a key with the default options and a random entropy

    -

    Implementors§

    Automatic implementation of GeneratableDefaultOptions for GeneratableKeys where +

    Provided Methods§

    Generate a key with the default options and a given entropy

    +

    Generate a key with the default options and a random entropy

    +

    Implementors§

    Automatic implementation of GeneratableDefaultOptions for GeneratableKeys where Options implements Default

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html index c8352b7620..e3e57f2de0 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html @@ -1,5 +1,4 @@ -GeneratableKey in bdk::keys - Rust

    Trait bdk::keys::GeneratableKey

    source ·
    pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
    +GeneratableKey in bdk::keys - Rust

    Trait bdk::keys::GeneratableKey

    source ·
    pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
         type Entropy: AsMut<[u8]> + Default;
         type Options;
         type Error: Debug;
    @@ -13,9 +12,9 @@
     implements it, the returned GeneratedKey will also implement it. The same is true for
     IntoDescriptorKey: the generated keys can be directly used in descriptors if Self is also
     IntoDescriptorKey.

    -

    Required Associated Types§

    Type specifying the amount of entropy required e.g. [u8;32]

    -

    Extra options required by the generate_with_entropy

    -

    Returned error in case of failure

    -

    Required Methods§

    Generate a key given the extra options and the entropy

    -

    Provided Methods§

    Generate a key given the options with a random entropy

    -

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file +

    Required Associated Types§

    Type specifying the amount of entropy required e.g. [u8;32]

    +

    Extra options required by the generate_with_entropy

    +

    Returned error in case of failure

    +

    Required Methods§

    Generate a key given the extra options and the entropy

    +

    Provided Methods§

    Generate a key given the options with a random entropy

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html index f147b4174b..e216e8c6b5 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html @@ -1,5 +1,4 @@ -IntoDescriptorKey in bdk::keys - Rust

    Trait bdk::keys::IntoDescriptorKey

    source ·
    pub trait IntoDescriptorKey<Ctx: ScriptContext>: Sized {
    +IntoDescriptorKey in bdk::keys - Rust

    Trait bdk::keys::IntoDescriptorKey

    source ·
    pub trait IntoDescriptorKey<Ctx: ScriptContext>: Sized {
         fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>;
     }
    Expand description

    Trait for objects that can be turned into a public or secret DescriptorKey

    The generic type Ctx is used to define the context in which the key is valid: some key @@ -81,7 +80,7 @@ are misused. In this case, the “segwit-only” key is used to build a pk makes the compiler (correctly) fail.

    ⓘ
    use bdk::bitcoin::PublicKey;
    -use std::str::FromStr;
    +use core::str::FromStr;
     
     use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError};
     
    @@ -101,6 +100,6 @@ makes the compiler (correctly) fail.

    let (descriptor, _, _) = bdk::descriptor!(pkh(key))?; // ^^^^^ changing this to `wpkh` would make it compile
    -

    Required Methods§

    Turn the key into a DescriptorKey within the requested ScriptContext

    -

    Implementations on Foreign Types§

    Implementors§

    The “identity” conversion is used internally by some bdk::fragments

    -
    \ No newline at end of file +

    Required Methods§

    Turn the key into a DescriptorKey within the requested ScriptContext

    +

    Implementations on Foreign Types§

    Implementors§

    The “identity” conversion is used internally by some bdk::fragments

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html index 44df5b0fc7..40c96819e0 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html @@ -1,5 +1,4 @@ -ScriptContext in bdk::keys - Rust

    Trait bdk::keys::ScriptContext

    pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
    +ScriptContext in bdk::keys - Rust

    Trait bdk::keys::ScriptContext

    pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
         type Key: ParseableKey<Sha256 = Hash, Hash256 = Hash, Ripemd160 = Hash, Hash160 = Hash> + MiniscriptKey;
     
     
    Show 15 methods fn check_terminal_non_malleable<Pk>(
            _frag: &Terminal<Pk, Self>
        ) -> Result<(), ScriptContextError>
        where
            Pk: MiniscriptKey
    ; diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html index a2e9d34d12..47dd7ea6a5 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html @@ -1,5 +1,4 @@ -KeyMap in bdk::keys - Rust

    Type Definition bdk::keys::KeyMap

    Expand description

    Alias type for a map of public key to secret key

    +KeyMap in bdk::keys - Rust

    Type Definition bdk::keys::KeyMap

    Expand description

    Alias type for a map of public key to secret key

    This map is returned whenever a descriptor that contains secrets is parsed using Descriptor::parse_descriptor, since the descriptor will always only contain public keys. This map allows looking up the corresponding secret key given a diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html index 568181f2ce..450e4fa6b3 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html @@ -1,3 +1,2 @@ -ValidNetworks in bdk::keys - Rust

    Type Definition bdk::keys::ValidNetworks

    source ·
    pub type ValidNetworks = HashSet<Network>;
    Expand description

    Set of valid networks for a key

    +ValidNetworks in bdk::keys - Rust

    Type Definition bdk::keys::ValidNetworks

    source ·
    pub type ValidNetworks = HashSet<Network>;
    Expand description

    Set of valid networks for a key

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html index 308997fb8d..f3b638a578 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html @@ -1,5 +1,4 @@ -descriptor in bdk - Rust

    Macro bdk::descriptor

    source ·
    macro_rules! descriptor {
    +descriptor in bdk - Rust

    Macro bdk::descriptor

    source ·
    macro_rules! descriptor {
         ( bare ( $( $minisc:tt )* ) ) => { ... };
         ( sh ( wsh ( $( $minisc:tt )* ) ) ) => { ... };
         ( shwsh ( $( $minisc:tt )* ) ) => { ... };
    @@ -30,7 +29,7 @@ descriptor syntax.


    2-of-3 that becomes a 1-of-3 after a timelock has expired. Both descriptor_a and descriptor_b are equivalent: the first syntax is more suitable for a fixed number of items known at compile time, while the other accepts a -Vec of items, which makes it more suitable for writing dynamic descriptors.

    +Vec of items, which makes it more suitable for writing dynamic descriptors.

    They both produce the descriptor: wsh(thresh(2,pk(...),s:pk(...),sndv:older(...)))

    let my_key_1 = bitcoin::PublicKey::from_str(
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html
    index 964d8c119f..c30d166ba7 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html
    @@ -1,5 +1,4 @@
    -fragment in bdk - Rust

    Macro bdk::fragment

    source ·
    macro_rules! fragment {
    +fragment in bdk - Rust

    Macro bdk::fragment

    source ·
    macro_rules! fragment {
         ( $modif:tt : $( $tail:tt )* ) => { ... };
         ( true ) => { ... };
         ( false ) => { ... };
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/index.html
    index 4ea6962910..a3255afd9f 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/index.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/index.html
    @@ -1,3 +1,2 @@
    -bdk::psbt - Rust

    Module bdk::psbt

    source ·
    Expand description

    Additional functions on the rust-bitcoin PartiallySignedTransaction structure.

    +bdk::psbt - Rust

    Module bdk::psbt

    source ·
    Expand description

    Additional functions on the rust-bitcoin PartiallySignedTransaction structure.

    Traits

    Trait to add functions to extract utxos and calculate fees.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/trait.PsbtUtils.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/trait.PsbtUtils.html index a6ee42fa14..15a9ec29e6 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/trait.PsbtUtils.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/trait.PsbtUtils.html @@ -1,14 +1,13 @@ -PsbtUtils in bdk::psbt - Rust

    Trait bdk::psbt::PsbtUtils

    source ·
    pub trait PsbtUtils {
    +PsbtUtils in bdk::psbt - Rust

    Trait bdk::psbt::PsbtUtils

    source ·
    pub trait PsbtUtils {
         fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
         fn fee_amount(&self) -> Option<u64>;
         fn fee_rate(&self) -> Option<FeeRate>;
     }
    Expand description

    Trait to add functions to extract utxos and calculate fees.

    -

    Required Methods§

    Get the TxOut for the specified input index, if it doesn’t exist in the PSBT None is returned.

    -

    The total transaction fee amount, sum of input amounts minus sum of output amounts, in sats. +

    Required Methods§

    Get the TxOut for the specified input index, if it doesn’t exist in the PSBT None is returned.

    +

    The total transaction fee amount, sum of input amounts minus sum of output amounts, in sats. If the PSBT is missing a TxOut for an input returns None.

    -

    The transaction’s fee rate. This value will only be accurate if calculated AFTER the +

    The transaction’s fee rate. This value will only be accurate if calculated AFTER the PartiallySignedTransaction is finalized and all witness/signature data is added to the transaction. If the PSBT is missing a TxOut for an input returns None.

    -

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js index 81a6afbae0..07d6cfea2a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"enum":[["Error","Errors that can be thrown by the `Wallet`"],["KeychainKind","Types of keychains"],["Utxo","An unspent transaction output (UTXO)."]],"externcrate":[["bitcoin",""],["bitcoincore_rpc",""],["electrum_client",""],["esplora_client",""],["hwi",""],["miniscript",""],["rusqlite",""],["sled",""]],"fn":[["version","Get the version of BDK at runtime"]],"macro":[["descriptor","Macro to write full descriptors with code"],["fragment","Macro to write descriptor fragments with code"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["keys","Key formats"],["psbt","Additional functions on the `rust-bitcoin` `PartiallySignedTransaction` structure."],["wallet","Wallet"]],"struct":[["Balance","Balance differentiated in various categories"],["BlockTime","Block height and timestamp of a block"],["FeeRate","Fee rate"],["LocalUtxo","An unspent output owned by a `Wallet`."],["TransactionDetails","A wallet transaction"],["WeightedUtxo","A [`Utxo`] with its `satisfaction_weight`."]],"trait":[["Vbytes","Trait implemented by types that can be used to measure weight units."]],"type":[["ConfirmationTime","DEPRECATED: Confirmation time of a transaction"]]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"enum":[["Error","Errors that can be thrown by the `Wallet`"],["KeychainKind","Types of keychains"],["Utxo","An unspent transaction output (UTXO)."]],"externcrate":[["bitcoin",""],["miniscript",""]],"fn":[["version","Get the version of BDK at runtime"]],"macro":[["descriptor","Macro to write full descriptors with code"],["fragment","Macro to write descriptor fragments with code"]],"mod":[["descriptor","Descriptors"],["keys","Key formats"],["psbt","Additional functions on the `rust-bitcoin` `PartiallySignedTransaction` structure."],["wallet","Wallet"]],"struct":[["FeeRate","Fee rate"],["LocalUtxo","An unspent output owned by a `Wallet`."],["TransactionDetails","A wallet transaction"],["WeightedUtxo","A [`Utxo`] with its `satisfaction_weight`."]],"trait":[["Vbytes","Trait implemented by types that can be used to measure weight units."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.Balance.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.Balance.html deleted file mode 100644 index de7d4ef319..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.Balance.html +++ /dev/null @@ -1,21 +0,0 @@ -Balance in bdk - Rust

    Struct bdk::Balance

    source ·
    pub struct Balance {
    -    pub immature: u64,
    -    pub trusted_pending: u64,
    -    pub untrusted_pending: u64,
    -    pub confirmed: u64,
    -}
    Expand description

    Balance differentiated in various categories

    -

    Fields§

    §immature: u64

    All coinbase outputs not yet matured

    -
    §trusted_pending: u64

    Unconfirmed UTXOs generated by a wallet tx

    -
    §untrusted_pending: u64

    Unconfirmed UTXOs received from an external wallet

    -
    §confirmed: u64

    Confirmed and immediately spendable balance

    -

    Implementations§

    Get sum of trusted_pending and confirmed coins

    -

    Get the whole balance visible to the wallet

    -

    Trait Implementations§

    The resulting type after applying the + operator.
    Performs the + operation. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used -by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more
    Method which takes an iterator and generates Self from the elements by -“summing up” the items. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.BlockTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.BlockTime.html deleted file mode 100644 index ff0b97cc82..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.BlockTime.html +++ /dev/null @@ -1,17 +0,0 @@ -BlockTime in bdk - Rust

    Struct bdk::BlockTime

    source ·
    pub struct BlockTime {
    -    pub height: u32,
    -    pub timestamp: u64,
    -}
    Expand description

    Block height and timestamp of a block

    -

    Fields§

    §height: u32

    confirmation block height

    -
    §timestamp: u64

    confirmation block timestamp

    -

    Implementations§

    Returns Some BlockTime if both height and timestamp are Some

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Converts to this type from the input type.
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used -by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= -operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html index 77057a6877..840164f507 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html @@ -1,25 +1,24 @@ -FeeRate in bdk - Rust

    Struct bdk::FeeRate

    source ·
    pub struct FeeRate(_);
    Expand description

    Fee rate

    -

    Implementations§

    Create a new instance of FeeRate given a float fee rate in sats/kwu

    -

    Create a new instance of FeeRate given a float fee rate in sats/kvb

    -

    Create a new instance of FeeRate given a float fee rate in btc/kvbytes

    +FeeRate in bdk - Rust

    Struct bdk::FeeRate

    source ·
    pub struct FeeRate(_);
    Expand description

    Fee rate

    +

    Implementations§

    Create a new instance of FeeRate given a float fee rate in sats/kwu

    +

    Create a new instance of FeeRate given a float fee rate in sats/kvb

    +

    Create a new instance of FeeRate given a float fee rate in btc/kvbytes

    Panics

    Panics if the value is not normal (except if it’s a positive zero) or negative.

    -

    Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

    +

    Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

    Panics

    Panics if the value is not normal (except if it’s a positive zero) or negative.

    -

    Create a new FeeRate with the default min relay fee value

    -

    Calculate fee rate from fee and weight units (wu).

    -

    Calculate fee rate from fee and vbytes.

    -

    Return the value as satoshi/vbyte

    -

    Calculate absolute fee in Satoshis using size in weight units.

    -

    Calculate absolute fee in Satoshis using size in virtual bytes.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    This method tests for self and other values to be equal, and is used +

    Create a new FeeRate with the default min relay fee value

    +

    Calculate fee rate from fee and weight units (wu).

    +

    Calculate fee rate from fee and vbytes.

    +

    Return the value as satoshi/vbyte

    +

    Calculate absolute fee in Satoshis using size in weight units.

    +

    Calculate absolute fee in Satoshis using size in virtual bytes.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
    The resulting type after applying the - operator.
    Performs the - operation. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more
    The resulting type after applying the - operator.
    Performs the - operation. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html index 23c568cced..2c24f0f713 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html @@ -1,18 +1,21 @@ -LocalUtxo in bdk - Rust

    Struct bdk::LocalUtxo

    source ·
    pub struct LocalUtxo {
    +LocalUtxo in bdk - Rust

    Struct bdk::LocalUtxo

    source ·
    pub struct LocalUtxo {
         pub outpoint: OutPoint,
         pub txout: TxOut,
         pub keychain: KeychainKind,
         pub is_spent: bool,
    +    pub derivation_index: u32,
    +    pub confirmation_time: ConfirmationTime,
     }
    Expand description

    An unspent output owned by a Wallet.

    Fields§

    §outpoint: OutPoint

    Reference to a transaction output

    §txout: TxOut

    Transaction output

    §keychain: KeychainKind

    Type of keychain

    §is_spent: bool

    Whether this UTXO is spent or not

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method tests for self and other values to be equal, and is used +
    §derivation_index: u32

    The derivation index for the script pubkey in the wallet

    +
    §confirmation_time: ConfirmationTime

    The confirmation time for transaction containing this utxo

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html index eaeb893b26..7d9b6380ca 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html @@ -1,11 +1,10 @@ -TransactionDetails in bdk - Rust

    Struct bdk::TransactionDetails

    source ·
    pub struct TransactionDetails {
    +TransactionDetails in bdk - Rust

    Struct bdk::TransactionDetails

    source ·
    pub struct TransactionDetails {
         pub transaction: Option<Transaction>,
         pub txid: Txid,
         pub received: u64,
         pub sent: u64,
         pub fee: Option<u64>,
    -    pub confirmation_time: Option<BlockTime>,
    +    pub confirmation_time: ConfirmationTime,
     }
    Expand description

    A wallet transaction

    Fields§

    §transaction: Option<Transaction>

    Optional transaction

    §txid: Txid

    Transaction id

    @@ -13,18 +12,15 @@ Sum of owned outputs of this transaction.

    §sent: u64

    Sent value (sats) Sum of owned inputs of this transaction.

    -
    §fee: Option<u64>

    Fee value (sats) if confirmed. -The availability of the fee depends on the backend. It’s never None with an Electrum -Server backend, but it could be None with a Bitcoin RPC node without txindex that receive -funds while offline.

    -
    §confirmation_time: Option<BlockTime>

    If the transaction is confirmed, contains height and Unix timestamp of the block containing the +

    §fee: Option<u64>

    Fee value in sats if it was available.

    +
    §confirmation_time: ConfirmationTime

    If the transaction is confirmed, contains height and Unix timestamp of the block containing the transaction, unconfirmed transaction contains None.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html index 32b8893c89..2655a7b550 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html @@ -1,15 +1,14 @@ -WeightedUtxo in bdk - Rust

    Struct bdk::WeightedUtxo

    source ·
    pub struct WeightedUtxo {
    +WeightedUtxo in bdk - Rust

    Struct bdk::WeightedUtxo

    source ·
    pub struct WeightedUtxo {
         pub satisfaction_weight: usize,
         pub utxo: Utxo,
     }
    Expand description

    A Utxo with its satisfaction_weight.

    Fields§

    §satisfaction_weight: usize

    The weight of the witness data and scriptSig expressed in weight units. This is used to properly maintain the feerate when adding this input to a transaction during coin selection.

    §utxo: Utxo

    The UTXO

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html index a788ecf07f..1f9e1c75be 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html @@ -1,6 +1,5 @@ -Vbytes in bdk - Rust

    Trait bdk::Vbytes

    source ·
    pub trait Vbytes {
    +Vbytes in bdk - Rust

    Trait bdk::Vbytes

    source ·
    pub trait Vbytes {
         fn vbytes(self) -> usize;
     }
    Expand description

    Trait implemented by types that can be used to measure weight units.

    -

    Required Methods§

    Convert weight units to virtual bytes.

    -

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file +

    Required Methods§

    Convert weight units to virtual bytes.

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/type.ConfirmationTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/type.ConfirmationTime.html deleted file mode 100644 index bea7bb14d2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/type.ConfirmationTime.html +++ /dev/null @@ -1,4 +0,0 @@ -ConfirmationTime in bdk - Rust

    Type Definition bdk::ConfirmationTime

    source ·
    pub type ConfirmationTime = BlockTime;
    👎Deprecated: This structure has been renamed to BlockTime
    Expand description

    DEPRECATED: Confirmation time of a transaction

    -

    The structure has been renamed to BlockTime

    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.Balance.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.Balance.html deleted file mode 100644 index 49e1ffffe8..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.Balance.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/struct.Balance.html...

    - - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.BlockTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.BlockTime.html deleted file mode 100644 index 1aeb0d712d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.BlockTime.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/struct.BlockTime.html...

    - - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/type.ConfirmationTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/type.ConfirmationTime.html deleted file mode 100644 index 52ce4499bb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/type.ConfirmationTime.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/type.ConfirmationTime.html...

    - - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Excess.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Excess.html index 3cf8febb2c..9b8b589374 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Excess.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Excess.html @@ -1,5 +1,4 @@ -Excess in bdk::wallet::coin_selection - Rust
    pub enum Excess {
    +Excess in bdk::wallet::coin_selection - Rust
    pub enum Excess {
         NoChange {
             dust_threshold: u64,
             remaining_amount: u64,
    @@ -17,8 +16,8 @@
     
    §

    Change

    Fields

    §amount: u64

    Effective amount available to create change after deducting the change output fee

    §fee: u64

    The deducted change output fee

    It’s possible to create spendable output from excess using the current drain output

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/fn.decide_change.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/fn.decide_change.html index 94db309635..c188854991 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/fn.decide_change.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/fn.decide_change.html @@ -1,5 +1,4 @@ -decide_change in bdk::wallet::coin_selection - Rust
    pub fn decide_change(
        remaining_amount: u64,
        fee_rate: FeeRate,
        drain_script: &Script
    ) -> Excess
    Expand description

    Decide if change can be created

    +decide_change in bdk::wallet::coin_selection - Rust
    pub fn decide_change(
        remaining_amount: u64,
        fee_rate: FeeRate,
        drain_script: &Script
    ) -> Excess
    Expand description

    Decide if change can be created

    Fields§

    §selected: Vec<Utxo>

    List of outputs selected for use as inputs

    §fee_amount: u64

    Total fee amount for the selected utxos in satoshis

    §excess: Excess

    Remaining amount after deducing fees and outgoing outputs

    -

    Implementations§

    The total value of the inputs selected.

    -

    The total value of the inputs selected from the local wallet.

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Implementations§

    The total value of the inputs selected.

    +

    The total value of the inputs selected from the local wallet.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html index 39612b53c6..1930f6883d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html @@ -1,9 +1,8 @@ -LargestFirstCoinSelection in bdk::wallet::coin_selection - Rust
    pub struct LargestFirstCoinSelection;
    Expand description

    Simple and dumb coin selection

    +LargestFirstCoinSelection in bdk::wallet::coin_selection - Rust
    pub struct LargestFirstCoinSelection;
    Expand description

    Simple and dumb coin selection

    This coin selection algorithm sorts the available UTXOs by value and then picks them starting from the largest ones until the required amount is reached.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Perform the coin selection Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Perform the coin selection Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.OldestFirstCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.OldestFirstCoinSelection.html index 68b86219a7..335d440ece 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.OldestFirstCoinSelection.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.OldestFirstCoinSelection.html @@ -1,9 +1,8 @@ -OldestFirstCoinSelection in bdk::wallet::coin_selection - Rust
    pub struct OldestFirstCoinSelection;
    Expand description

    OldestFirstCoinSelection always picks the utxo with the smallest blockheight to add to the selected coins next

    +OldestFirstCoinSelection in bdk::wallet::coin_selection - Rust
    pub struct OldestFirstCoinSelection;
    Expand description

    OldestFirstCoinSelection always picks the utxo with the smallest blockheight to add to the selected coins next

    This coin selection algorithm sorts the available UTXOs by blockheight and then picks them starting from the oldest ones until the required amount is reached.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Perform the coin selection Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Perform the coin selection Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html index 3d7ab45330..13d983ffa8 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html @@ -1,11 +1,10 @@ -CoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust
    pub trait CoinSelectionAlgorithm<D: Database>: Debug {
    -    fn coin_select(
            &self,
            database: &D,
            required_utxos: Vec<WeightedUtxo>,
            optional_utxos: Vec<WeightedUtxo>,
            fee_rate: FeeRate,
            target_amount: u64,
            drain_script: &Script
        ) -> Result<CoinSelectionResult, Error>; +CoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust
    pub trait CoinSelectionAlgorithm: Debug {
    +    fn coin_select(
            &self,
            required_utxos: Vec<WeightedUtxo>,
            optional_utxos: Vec<WeightedUtxo>,
            fee_rate: FeeRate,
            target_amount: u64,
            drain_script: &Script
        ) -> Result<CoinSelectionResult, Error>; }
    Expand description

    Trait for generalized coin selection algorithms

    This trait can be implemented to make the Wallet use a customized coin selection algorithm when it creates transactions.

    For an example see this module’s documentation.

    -

    Required Methods§

    Perform the coin selection

    +

    Required Methods§

    Perform the coin selection

    • database: a reference to the wallet’s database that can be used to lookup additional details for a specific UTXO
    • @@ -18,4 +17,4 @@ weight cost accumulated from added outputs and transaction’s header.
    • drain_script: the script to use in case of change
    -

    Implementors§

    \ No newline at end of file +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html index 46d482c6dd..4e9323b691 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html @@ -1,4 +1,3 @@ -DefaultCoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust
    pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
    Expand description

    Default coin selection algorithm used by TxBuilder if not +DefaultCoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust

    pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
    Expand description

    Default coin selection algorithm used by TxBuilder if not overridden

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html index c652ad6ad6..34189eed4e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html @@ -1,9 +1,7 @@ -AddressIndex in bdk::wallet - Rust

    Enum bdk::wallet::AddressIndex

    source ·
    pub enum AddressIndex {
    +AddressIndex in bdk::wallet - Rust

    Enum bdk::wallet::AddressIndex

    source ·
    pub enum AddressIndex {
         New,
         LastUnused,
         Peek(u32),
    -    Reset(u32),
     }
    Expand description

    The address index selection strategy to use to derived an address from the wallet’s external descriptor. See Wallet::get_address. If you’re unsure which one to use use WalletIndex::New.

    Variants§

    §

    New

    Return a new address after incrementing the current descriptor index.

    @@ -17,15 +15,8 @@ web page.

    index used by AddressIndex::New and AddressIndex::LastUsed.

    Use with caution, if an index is given that is less than the current descriptor index then the returned address may have already been used.

    -
    §

    Reset(u32)

    Return the address for a specific descriptor index and reset the current descriptor index -used by AddressIndex::New and AddressIndex::LastUsed to this value.

    -

    Use with caution, if an index is given that is less than the current descriptor index -then the returned address and subsequent addresses returned by calls to AddressIndex::New -and AddressIndex::LastUsed may have already been used. Also if the index is reset to a -value earlier than the crate::blockchain::Blockchain stop_gap (default is 20) then a -larger stop_gap should be used to monitor for all possibly used addresses.

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.NewError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.NewError.html new file mode 100644 index 0000000000..191e7c7432 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.NewError.html @@ -0,0 +1,12 @@ +NewError in bdk::wallet - Rust

    Enum bdk::wallet::NewError

    source ·
    pub enum NewError<P> {
    +    Descriptor(DescriptorError),
    +    Persist(P),
    +}
    Expand description

    Error returned from Wallet::new

    +

    Variants§

    §

    Descriptor(DescriptorError)

    There was problem with the descriptors passed in

    +
    §

    Persist(P)

    We were unable to load the wallet’s data from the persistance backend

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html index 44ce4ea373..9e940f7be4 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html @@ -1,5 +1,4 @@ -bdk::wallet::export - Rust

    Module bdk::wallet::export

    source ·
    Expand description

    Wallet export

    +bdk::wallet::export - Rust

    Module bdk::wallet::export

    source ·
    Expand description

    Wallet export

    This modules implements the wallet export format used by FullyNoded.

    Examples

    Import from JSON

    let import = r#"{
    @@ -9,22 +8,18 @@
     }"#;
     
     let import = FullyNodedExport::from_str(import)?;
    -let wallet = Wallet::new(
    +let wallet = Wallet::new_no_persist(
         &import.descriptor(),
         import.change_descriptor().as_ref(),
         Network::Testnet,
    -    MemoryDatabase::default(),
     )?;

    Export a Wallet

    -
    let wallet = Wallet::new(
    +
    let wallet = Wallet::new_no_persist(
         "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
         Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
         Network::Testnet,
    -    MemoryDatabase::default()
     )?;
    -let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true)
    -    .map_err(ToString::to_string)
    -    .map_err(bdk::Error::Generic)?;
    +let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true).unwrap();
     
     println!("Exported: {}", export.to_string());

    Structs

    Structure that contains the export of a wallet

    Type Definitions

    WalletExportDeprecated
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.FullyNodedExport.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.FullyNodedExport.html index 645f7a33f9..d3e2351491 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.FullyNodedExport.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.FullyNodedExport.html @@ -1,5 +1,4 @@ -FullyNodedExport in bdk::wallet::export - Rust

    Fields§

    §blockheight: u32

    Earliest block to rescan when looking for the wallet’s transactions

    §label: String

    Arbitrary label for the wallet

    -

    Implementations§

    Export a wallet

    +

    Implementations§

    Export a wallet

    This function returns an error if it determines that the wallet’s descriptor(s) are not supported by Bitcoin Core or don’t follow the standard derivation paths defined by BIP44 and others.

    @@ -15,10 +14,10 @@ and others.

    for the oldest transaction it knows and use that as the earliest block to rescan.

    If the database is empty or include_blockheight is false, the blockheight field returned will be 0.

    -

    Return the external descriptor

    -

    Return the internal descriptor, if present

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more
    Serialize this value into the given Serde serializer. Read more
    Converts the given value to a String. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Return the external descriptor

    +

    Return the internal descriptor, if present

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more
    Serialize this value into the given Serde serializer. Read more
    Converts the given value to a String. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/type.WalletExport.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/type.WalletExport.html index c2c927378c..8c6ef7d9d7 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/type.WalletExport.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/type.WalletExport.html @@ -1,3 +1,2 @@ -WalletExport in bdk::wallet::export - Rust

    Type Definition bdk::wallet::export::WalletExport

    source ·
    pub type WalletExport = FullyNodedExport;
    👎Deprecated since 0.18.0: Please use [FullyNodedExport] instead
    Expand description

    Alias for FullyNodedExport

    +WalletExport in bdk::wallet::export - Rust

    Type Definition bdk::wallet::export::WalletExport

    source ·
    pub type WalletExport = FullyNodedExport;
    👎Deprecated since 0.18.0: Please use [FullyNodedExport] instead
    Expand description

    Alias for FullyNodedExport

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html deleted file mode 100644 index a7b3ab8a25..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html +++ /dev/null @@ -1,3 +0,0 @@ -get_funded_wallet in bdk::wallet - Rust

    Function bdk::wallet::get_funded_wallet

    source ·
    pub fn get_funded_wallet(
        descriptor: &str
    ) -> (Wallet<AnyDatabase>, (String, Option<String>), Txid)
    Expand description

    Return a fake wallet that appears to be funded for testing.

    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.wallet_name_from_descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.wallet_name_from_descriptor.html index 7e829b7331..ed6903b2ec 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.wallet_name_from_descriptor.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.wallet_name_from_descriptor.html @@ -1,4 +1,3 @@ -wallet_name_from_descriptor in bdk::wallet - Rust
    pub fn wallet_name_from_descriptor<T>(
        descriptor: T,
        change_descriptor: Option<T>,
        network: Network,
        secp: &Secp256k1<All>
    ) -> Result<String, Error>where
        T: IntoWalletDescriptor,
    Expand description

    Deterministically generate a unique name given the descriptors defining the wallet

    +wallet_name_from_descriptor in bdk::wallet - Rust
    pub fn wallet_name_from_descriptor<T>(
        descriptor: T,
        change_descriptor: Option<T>,
        network: Network,
        secp: &Secp256k1<All>
    ) -> Result<String, Error>where
        T: IntoWalletDescriptor,
    Expand description

    Deterministically generate a unique name given the descriptors defining the wallet

    Compatible with wallet_name_from_descriptor

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/index.html deleted file mode 100644 index 2f85ddd38a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/index.html +++ /dev/null @@ -1,20 +0,0 @@ -bdk::wallet::hardwaresigner - Rust

    Module bdk::wallet::hardwaresigner

    source ·
    Available on crate feature hardware-signer only.
    Expand description

    HWI Signer

    -

    This module contains HWISigner, an implementation of a TransactionSigner to be -used with hardware wallets.

    - -
    let mut devices = HWIClient::enumerate()?;
    -if devices.is_empty() {
    -    panic!("No devices found!");
    -}
    -let first_device = devices.remove(0)?;
    -let custom_signer = HWISigner::from_device(&first_device, HWIChain::Test)?;
    -
    -// Adding the hardware signer to the BDK wallet
    -wallet.add_signer(
    -    KeychainKind::External,
    -    SignerOrdering(200),
    -    Arc::new(custom_signer),
    -);
    -
    -

    Structs

    Custom signer for Hardware Wallets
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/sidebar-items.js deleted file mode 100644 index 1db16cc1ab..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"struct":[["HWISigner","Custom signer for Hardware Wallets"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/struct.HWISigner.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/struct.HWISigner.html deleted file mode 100644 index 6419904e66..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/hardwaresigner/struct.HWISigner.html +++ /dev/null @@ -1,10 +0,0 @@ -HWISigner in bdk::wallet::hardwaresigner - Rust
    pub struct HWISigner { /* private fields */ }
    Available on crate feature hardware-signer only.
    Expand description

    Custom signer for Hardware Wallets

    -

    This ignores sign_options and leaves the decisions up to the hardware wallet.

    -

    Implementations§

    Create a instance from the specified device and chain

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Return the SignerId for this signer Read more
    Return the secret key for the signer Read more

    This implementation ignores sign_options

    -
    Sign all the inputs of the psbt

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html index db13000761..3bff530636 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html @@ -1,8 +1,8 @@ -bdk::wallet - Rust

    Module bdk::wallet

    source ·
    Expand description

    Wallet

    +bdk::wallet - Rust

    Module bdk::wallet

    source ·
    Expand description

    Wallet

    This module defines the Wallet structure.

    -

    Modules

    Coin selection
    Wallet export
    hardwaresignerhardware-signer
    HWI Signer
    Generalized signers
    Cross-platform time
    Transaction builder
    verifyverify
    Verify transactions against the consensus rules

    Structs

    A derived address and the index it was found at. -For convenience this automatically derefs to Address
    Options to a sync.
    A Bitcoin wallet

    Enums

    The address index selection strategy to use to derived an address from the wallet’s external -descriptor. See Wallet::get_address. If you’re unsure which one to use use WalletIndex::New.

    Traits

    Trait to check if a value is below the dust limit. +

    Modules

    Coin selection
    Wallet export
    Generalized signers
    Transaction builder

    Structs

    A derived address and the index it was found at. +For convenience this automatically derefs to Address
    Balance differentiated in various categories.
    A Bitcoin wallet

    Enums

    The address index selection strategy to use to derived an address from the wallet’s external +descriptor. See Wallet::get_address. If you’re unsure which one to use use WalletIndex::New.
    Error returned from Wallet::new

    Traits

    Trait to check if a value is below the dust limit. We are performing dust value calculation for a given script public key using rust-bitcoin to -keep it compatible with network dust rate

    Functions

    Return a fake wallet that appears to be funded for testing.
    Deterministically generate a unique name given the descriptors defining the wallet
    \ No newline at end of file +keep it compatible with network dust rate

    Functions

    Deterministically generate a unique name given the descriptors defining the wallet

    Type Definitions

    The update to a Wallet used in Wallet::apply_update. This is usually returned from blockchain data sources. +The type parameter T indicates the kind of transaction contained in the update. It’s usually a [bitcoin::Transaction].
    Error indicating that something was wrong with an Update<T>.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js index 8319a96a9d..41b994075c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"enum":[["AddressIndex","The address index selection strategy to use to derived an address from the wallet’s external descriptor. See [`Wallet::get_address`]. If you’re unsure which one to use use `WalletIndex::New`."]],"fn":[["get_funded_wallet","Return a fake wallet that appears to be funded for testing."],["wallet_name_from_descriptor","Deterministically generate a unique name given the descriptors defining the wallet"]],"mod":[["coin_selection","Coin selection"],["export","Wallet export"],["hardwaresigner","HWI Signer"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"],["verify","Verify transactions against the consensus rules"]],"struct":[["AddressInfo","A derived address and the index it was found at. For convenience this automatically derefs to `Address`"],["SyncOptions","Options to a `sync`."],["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit. We are performing dust value calculation for a given script public key using rust-bitcoin to keep it compatible with network dust rate"]]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"enum":[["AddressIndex","The address index selection strategy to use to derived an address from the wallet’s external descriptor. See [`Wallet::get_address`]. If you’re unsure which one to use use `WalletIndex::New`."],["NewError","Error returned from [`Wallet::new`]"]],"fn":[["wallet_name_from_descriptor","Deterministically generate a unique name given the descriptors defining the wallet"]],"mod":[["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["tx_builder","Transaction builder"]],"struct":[["AddressInfo","A derived address and the index it was found at. For convenience this automatically derefs to `Address`"],["Balance","Balance differentiated in various categories."],["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit. We are performing dust value calculation for a given script public key using rust-bitcoin to keep it compatible with network dust rate"]],"type":[["Update","The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources. The type parameter `T` indicates the kind of transaction contained in the update. It’s usually a [`bitcoin::Transaction`]."],["UpdateError","Error indicating that something was wrong with an [`Update`]."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerContext.html index a7e0878f6f..cc236cd89d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerContext.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerContext.html @@ -1,5 +1,4 @@ -SignerContext in bdk::wallet::signer - Rust
    pub enum SignerContext {
    +SignerContext in bdk::wallet::signer - Rust
    pub enum SignerContext {
         Legacy,
         Segwitv0,
         Tap {
    @@ -11,10 +10,10 @@
     
    §

    Segwitv0

    Segwit v0 context (BIP 143)

    §

    Tap

    Fields

    §is_internal_key: bool

    Whether the signer can sign for the internal key or not

    Taproot context (BIP 340)

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html index 098d629451..d011482edd 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html @@ -1,6 +1,5 @@ -SignerError in bdk::wallet::signer - Rust

    Enum bdk::wallet::signer::SignerError

    source ·
    Expand description

    Signing error

    +}
    Expand description

    Signing error

    Variants§

    §

    MissingKey

    The private key is missing for the required public key

    §

    InvalidKey

    The private key in use has the right fingerprint but derives differently than expected

    §

    UserCanceled

    The user canceled the operation

    @@ -29,12 +27,11 @@ explicitly allowed them

    SignOptions::allow_all_sighashes to true.

    §

    InvalidSighash

    Invalid SIGHASH for the signing context in use

    §

    SighashError(Error)

    Error while computing the hash to sign

    -
    §

    HWIError(Error)

    Error while signing using hardware wallets

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html index b6559dfc35..30a78cfb95 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html @@ -1,5 +1,4 @@ -SignerId in bdk::wallet::signer - Rust

    Enum bdk::wallet::signer::SignerId

    source ·
    pub enum SignerId {
    +SignerId in bdk::wallet::signer - Rust

    Enum bdk::wallet::signer::SignerId

    source ·
    pub enum SignerId {
         PkHash(Hash),
         Fingerprint(Fingerprint),
         Dummy(u64),
    @@ -12,8 +11,8 @@ multiple of them

    by ==. Read more
    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.TapLeavesOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.TapLeavesOptions.html index d62ece1193..699d504c65 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.TapLeavesOptions.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.TapLeavesOptions.html @@ -1,5 +1,4 @@ -TapLeavesOptions in bdk::wallet::signer - Rust
    pub enum TapLeavesOptions {
    +TapLeavesOptions in bdk::wallet::signer - Rust
    pub enum TapLeavesOptions {
         All,
         Include(Vec<TapLeafHash>),
         Exclude(Vec<TapLeafHash>),
    @@ -10,10 +9,10 @@
     some of the specified leaves, if it doesn’t have the right key to sign them.

    §

    Exclude(Vec<TapLeafHash>)

    The signer won’t sign the specified leaves.

    §

    None

    The signer won’t sign any leaf.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html index 3a1eeb8fec..837521f985 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html @@ -1,5 +1,4 @@ -bdk::wallet::signer - Rust

    Module bdk::wallet::signer

    source ·
    Expand description

    Generalized signers

    +bdk::wallet::signer - Rust

    Module bdk::wallet::signer

    source ·
    Expand description

    Generalized signers

    This module provides the ability to add customized signers to a Wallet through the Wallet::add_signer function.

    @@ -37,7 +36,7 @@ through the Wallet::add_ let custom_signer = CustomSigner::connect(); let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)"; -let mut wallet = Wallet::new(descriptor, None, Network::Testnet, MemoryDatabase::default())?; +let mut wallet = Wallet::new_no_persist(descriptor, None, Network::Testnet)?; wallet.add_signer( KeychainKind::External, SignerOrdering(200), diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html index af7effc2bb..f1607efc3f 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html @@ -1,5 +1,4 @@ -SignOptions in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignOptions

    source ·
    pub struct SignOptions {
    +SignOptions in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignOptions

    source ·
    pub struct SignOptions {
         pub trust_witness_utxo: bool,
         pub assume_height: Option<u32>,
         pub allow_all_sighashes: bool,
    @@ -40,8 +39,8 @@ or not. This option is ignored if we’re signing a non-taproot PSBT.

    §allow_grinding: bool

    Whether we should grind ECDSA signature to ensure signing with low r or not. Defaults to true, i.e., we always grind ECDSA signature to sign with low r.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html index 227ae1c8a5..ad0c7819c4 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html @@ -1,14 +1,13 @@ -SignerOrdering in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignerOrdering

    source ·
    pub struct SignerOrdering(pub usize);
    Expand description

    Defines the order in which signers are called

    +SignerOrdering in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignerOrdering

    source ·
    pub struct SignerOrdering(pub usize);
    Expand description

    Defines the order in which signers are called

    The default value is 100. Signers with an ordering above that will be called later, and they will thus see the partial signatures added to the transaction once they get to sign themselves.

    -

    Tuple Fields§

    §0: usize

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +

    Tuple Fields§

    §0: usize

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerWrapper.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerWrapper.html index d3d122af59..88cda06bf6 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerWrapper.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerWrapper.html @@ -1,8 +1,7 @@ -SignerWrapper in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignerWrapper

    source ·
    pub struct SignerWrapper<S: Sized + Debug + Clone> { /* private fields */ }
    Expand description

    Wrapper structure to pair a signer with its context

    -

    Implementations§

    Create a wrapped signer from a signer and a context

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    The resulting type after dereferencing.
    Dereferences the value.
    Sign a single psbt input
    Sign a single psbt input
    Return the SignerId for this signer Read more
    Return the secret key for the signer Read more
    Return the SignerId for this signer Read more
    Return the secret key for the signer Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +SignerWrapper in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignerWrapper

    source ·
    pub struct SignerWrapper<S: Sized + Debug + Clone> { /* private fields */ }
    Expand description

    Wrapper structure to pair a signer with its context

    +

    Implementations§

    Create a wrapped signer from a signer and a context

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    The resulting type after dereferencing.
    Dereferences the value.
    Sign a single psbt input
    Sign a single psbt input
    Return the SignerId for this signer Read more
    Return the secret key for the signer Read more
    Return the SignerId for this signer Read more
    Return the secret key for the signer Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Sign all the inputs of the psbt
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Sign all the inputs of the psbt
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html index 1843d88fda..87911acd02 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html @@ -1,18 +1,17 @@ -SignersContainer in bdk::wallet::signer - Rust
    pub struct SignersContainer(_);
    Expand description

    Container for multiple signers

    -

    Implementations§

    Create a map of public keys to secret keys

    -

    Build a new signer container from a KeyMap

    +SignersContainer in bdk::wallet::signer - Rust
    pub struct SignersContainer(_);
    Expand description

    Container for multiple signers

    +

    Implementations§

    Create a map of public keys to secret keys

    +

    Build a new signer container from a KeyMap

    Also looks at the corresponding descriptor to determine the SignerContext to attach to the signers

    -

    Default constructor

    -

    Adds an external signer to the container for the specified id. Optionally returns the +

    Default constructor

    +

    Adds an external signer to the container for the specified id. Optionally returns the signer that was previously in the container, if any

    -

    Removes a signer from the container and returns it

    -

    Returns the list of identifiers of all the signers in the container

    -

    Returns the list of signers in the container, sorted by lowest to highest ordering

    -

    Finds the signer with lowest ordering for a given id in the container.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Removes a signer from the container and returns it

    +

    Returns the list of identifiers of all the signers in the container

    +

    Returns the list of signers in the container, sorted by lowest to highest ordering

    +

    Finds the signer with lowest ordering for a given id in the container.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.InputSigner.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.InputSigner.html index f94ca0e008..7796f18b8b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.InputSigner.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.InputSigner.html @@ -1,9 +1,8 @@ -InputSigner in bdk::wallet::signer - Rust

    Trait bdk::wallet::signer::InputSigner

    source ·
    pub trait InputSigner: SignerCommon {
    +InputSigner in bdk::wallet::signer - Rust

    Trait bdk::wallet::signer::InputSigner

    source ·
    pub trait InputSigner: SignerCommon {
         fn sign_input(
            &self,
            psbt: &mut PartiallySignedTransaction,
            input_index: usize,
            sign_options: &SignOptions,
            secp: &Secp256k1<All>
        ) -> Result<(), SignerError>; }
    Expand description

    PSBT Input signer

    This trait can be implemented to provide custom signers to the wallet. If the signer supports signing individual inputs, this trait should be implemented and BDK will provide automatically an implementation for TransactionSigner.

    -

    Required Methods§

    Sign a single psbt input

    -

    Implementors§

    \ No newline at end of file +

    Required Methods§

    Sign a single psbt input

    +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.SignerCommon.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.SignerCommon.html index be86517f7f..76fd825378 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.SignerCommon.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.SignerCommon.html @@ -1,14 +1,13 @@ -SignerCommon in bdk::wallet::signer - Rust

    Trait bdk::wallet::signer::SignerCommon

    source ·
    pub trait SignerCommon: Debug + Send + Sync {
    +SignerCommon in bdk::wallet::signer - Rust

    Trait bdk::wallet::signer::SignerCommon

    source ·
    pub trait SignerCommon: Debug + Send + Sync {
         fn id(&self, secp: &Secp256k1<All>) -> SignerId;
     
         fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... }
     }
    Expand description

    Common signer methods

    -

    Required Methods§

    Return the SignerId for this signer

    +

    Required Methods§

    Return the SignerId for this signer

    The SignerId can be used to lookup a signer in the Wallet’s signers map or to compare two signers.

    -

    Provided Methods§

    Return the secret key for the signer

    +

    Provided Methods§

    Return the secret key for the signer

    This is used internally to reconstruct the original descriptor that may contain secrets. External signers that are meant to keep key isolated should just return None here (which is the default for this method, if not overridden).

    -

    Implementors§

    \ No newline at end of file +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.TransactionSigner.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.TransactionSigner.html index a290486650..11d1829799 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.TransactionSigner.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.TransactionSigner.html @@ -1,9 +1,7 @@ -TransactionSigner in bdk::wallet::signer - Rust
    pub trait TransactionSigner: SignerCommon {
    +TransactionSigner in bdk::wallet::signer - Rust
    pub trait TransactionSigner: SignerCommon {
         fn sign_transaction(
            &self,
            psbt: &mut PartiallySignedTransaction,
            sign_options: &SignOptions,
            secp: &Secp256k1<All>
        ) -> Result<(), SignerError>; }
    Expand description

    PSBT signer

    This trait can be implemented when the signer can’t sign inputs individually, but signs the whole transaction at once.

    -

    Required Methods§

    Sign all the inputs of the psbt

    -

    Implementors§

    This implementation ignores sign_options

    -
    \ No newline at end of file +

    Required Methods§

    Sign all the inputs of the psbt

    +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html index b03187bc96..b15da7211a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html @@ -1,5 +1,4 @@ -AddressInfo in bdk::wallet - Rust

    Struct bdk::wallet::AddressInfo

    source ·
    pub struct AddressInfo {
    +AddressInfo in bdk::wallet - Rust

    Struct bdk::wallet::AddressInfo

    source ·
    pub struct AddressInfo {
         pub index: u32,
         pub address: Address,
         pub keychain: KeychainKind,
    @@ -45,10 +44,10 @@ given key. For taproot addresses, the supplied key is assumed to be tweaked

    Returns true if the supplied xonly public key can be used to derive the address.

    This will only work for Taproot addresses. The Public Key is assumed to have already been tweaked.

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    The resulting type after dereferencing.
    Dereferences the value.
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    The resulting type after dereferencing.
    Dereferences the value.
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html new file mode 100644 index 0000000000..6ad2e72d25 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html @@ -0,0 +1,21 @@ +Balance in bdk::wallet - Rust

    Struct bdk::wallet::Balance

    pub struct Balance {
    +    pub immature: u64,
    +    pub trusted_pending: u64,
    +    pub untrusted_pending: u64,
    +    pub confirmed: u64,
    +}
    Expand description

    Balance differentiated in various categories.

    +

    Fields§

    §immature: u64

    All coinbase outputs not yet matured

    +
    §trusted_pending: u64

    Unconfirmed UTXOs generated by a wallet tx

    +
    §untrusted_pending: u64

    Unconfirmed UTXOs received from an external wallet

    +
    §confirmed: u64

    Confirmed and immediately spendable balance

    +

    Implementations§

    Get sum of trusted_pending and confirmed coins.

    +

    This is the balance you can spend right now that shouldn’t get cancelled via another party +double spending it.

    +

    Get the whole balance visible to the wallet.

    +

    Trait Implementations§

    The resulting type after applying the + operator.
    Performs the + operation. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.SyncOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.SyncOptions.html deleted file mode 100644 index d07235640a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.SyncOptions.html +++ /dev/null @@ -1,10 +0,0 @@ -SyncOptions in bdk::wallet - Rust

    Struct bdk::wallet::SyncOptions

    source ·
    pub struct SyncOptions {
    -    pub progress: Option<Box<dyn Progress>>,
    -}
    Expand description

    Options to a sync.

    -

    Fields§

    §progress: Option<Box<dyn Progress>>

    The progress tracker which may be informed when progress is made.

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html index c3c9d86c1f..948f89426e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html @@ -1,70 +1,71 @@ -Wallet in bdk::wallet - Rust

    Struct bdk::wallet::Wallet

    source ·
    pub struct Wallet<D> { /* private fields */ }
    Expand description

    A Bitcoin wallet

    +Wallet in bdk::wallet - Rust

    Struct bdk::wallet::Wallet

    source ·
    pub struct Wallet<D = ()> { /* private fields */ }
    Expand description

    A Bitcoin wallet

    The Wallet struct acts as a way of coherently interfacing with output descriptors and related transactions. Its main components are:

    1. output descriptors from which it can derive addresses.
    2. -
    3. A Database where it tracks transactions and utxos related to the descriptors.
    4. signers that can contribute signatures to addresses instantiated from the descriptors.
    -

    Implementations§

    👎Deprecated: Just use Wallet::new – all wallets are offline now!

    Create a new “offline” wallet

    -

    Create a wallet.

    -

    The only way this can fail is if the descriptors passed in do not match the checksums in database.

    -

    Get the Bitcoin network the wallet is using.

    -

    Return a derived address using the external descriptor, see AddressIndex for +

    Implementations§

    Creates a wallet that does not persist data.

    +

    Create a wallet from a descriptor (and an optional change_descriptor) and load related +transaction data from db.

    +

    Get the Bitcoin network the wallet is using.

    +

    Iterator over all keychains in this wallet

    +

    Return a derived address using the external descriptor, see AddressIndex for available address index selection strategies. If none of the keys in the descriptor are derivable (i.e. does not end with /*) then the same address will always be returned for any AddressIndex.

    -

    Return a derived address using the internal (change) descriptor.

    +

    Return a derived address using the internal (change) descriptor.

    If the wallet doesn’t have an internal descriptor it will use the external descriptor.

    see AddressIndex for available address index selection strategies. If none of the keys in the descriptor are derivable (i.e. does not end with /*) then the same address will always be returned for any AddressIndex.

    -

    Ensures that there are at least max_addresses addresses cached in the database if the -descriptor is derivable, or 1 address if it is not. -Will return Ok(true) if there are new addresses generated (either external or internal), -and Ok(false) if all the required addresses are already cached. This function is useful to -explicitly cache addresses in a wallet to do things like check Wallet::is_mine on -transaction output scripts.

    -

    Return whether or not a script is part of this wallet (either internal or external)

    -

    Return the list of unspent outputs of this wallet

    -

    Note that this method only operates on the internal database, which first needs to be -Wallet::sync manually.

    -

    Returns the UTXO owned by this wallet corresponding to outpoint if it exists in the +

    Return whether or not a script is part of this wallet (either internal or external)

    +

    Finds how the wallet derived the script pubkey spk.

    +

    Will only return Some(_) if the wallet has given out the spk.

    +

    Return the list of unspent outputs of this wallet

    +

    Get all the checkpoints the wallet is currently storing indexed by height.

    +

    Returns the latest checkpoint.

    +

    Returns a iterators of all the script pubkeys for the Internal and Externalvariants inKeychainKind`.

    +

    This is inteded to be used when doing a full scan of your addresses (e.g. after restoring +from seed words). You pass the BTreeMap of iterators to a blockchain data source (e.g. +electrum server) which will go through each address until it reaches a stop grap.

    +

    Note carefully that iterators go over all script pubkeys on the keychains (not what +script pubkeys the wallet is storing internally).

    +

    Gets an iterator over all the script pubkeys in a single keychain.

    +

    See spks_of_all_keychains for more documentation

    +

    Returns the utxo owned by this wallet corresponding to outpoint if it exists in the wallet’s database.

    -

    Return a single transactions made and received by the wallet

    +

    Return a single transactions made and received by the wallet

    Optionally fill the TransactionDetails::transaction field with the raw transaction if include_raw is true.

    -

    Note that this method only operates on the internal database, which first needs to be -Wallet::sync manually.

    -

    Return an unsorted list of transactions made and received by the wallet

    -

    Optionally fill the TransactionDetails::transaction field with the raw transaction if -include_raw is true.

    -

    To sort transactions, the following code can be used:

    - -
    tx_list.sort_by(|a, b| {
    -    b.confirmation_time
    -        .as_ref()
    -        .map(|t| t.height)
    -        .cmp(&a.confirmation_time.as_ref().map(|t| t.height))
    -});
    -

    Note that this method only operates on the internal database, which first needs to be -Wallet::sync manually.

    -

    Return the balance, separated into available, trusted-pending, untrusted-pending and immature +

    Add a new checkpoint to the wallet’s internal view of the chain. +This stages but does not commit the change.

    +

    Returns whether anything changed with the insertion (e.g. false if checkpoint was already +there).

    +

    Add a transaction to the wallet’s internal view of the chain. +This stages but does not commit the change.

    +

    There are a number reasons tx could be rejected with an Err(_). The most important one +is that the transaction is at a height that is greater than latest_checkpoint. Therefore +you should use insert_checkpoint to insert new checkpoints before manually inserting new +transactions.

    +

    Returns whether anything changed with the transaction insertion (e.g. false if the +transaction was already inserted at the same position).

    +
    👎Deprecated: use Wallet::transactions instead

    Deprecated. use Wallet::transactions instead.

    +

    Iterate over the transactions in the wallet in order of ascending confirmation time with +unconfirmed transactions last.

    +

    Return the balance, separated into available, trusted-pending, untrusted-pending and immature values.

    -

    Note that this method only operates on the internal database, which first needs to be -Wallet::sync manually.

    -

    Add an external signer

    +

    Add an external signer

    See the signer module for an example.

    -

    Get the signers

    +

    Get the signers

    Example
    -
    let wallet = Wallet::new("wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*)", None, Network::Testnet, MemoryDatabase::new())?;
    +
    let wallet = Wallet::new_no_persist("wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*)", None, Network::Testnet)?;
     for secret_key in wallet.get_signers(KeychainKind::External).signers().iter().filter_map(|s| s.descriptor_secret_key()) {
         // secret_key: tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*
         println!("secret_key: {}", secret_key);
     }
     
     Ok::<(), Box<dyn std::error::Error>>(())
    -

    Start building a transaction.

    +

    Start building a transaction.

    This returns a blank TxBuilder from which you can specify the parameters for the transaction.

    Example
    let (psbt, details) = {
    @@ -75,7 +76,7 @@ values.

    }; // sign and broadcast ...
    -

    Bump the fee of a transaction previously created with this wallet.

    +

    Bump the fee of a transaction previously created with this wallet.

    Returns an error if the transaction is already confirmed or doesn’t explicitly signal replace by fee (RBF). If the transaction can be fee bumped then it returns a TxBuilder pre-populated with the inputs and outputs of the original transaction.

    @@ -100,7 +101,7 @@ pre-populated with the inputs and outputs of the original transaction.

    let _ = wallet.sign(&mut psbt, SignOptions::default())?; let fee_bumped_tx = psbt.extract_tx(); // broadcast fee_bumped_tx to replace original
    -

    Sign a transaction with all the wallet’s signers, in the order specified by every signer’s +

    Sign a transaction with all the wallet’s signers, in the order specified by every signer’s SignerOrdering. This function returns the Result type with an encapsulated bool that has the value true if the PSBT was finalized, or false otherwise.

    The SignOptions can be used to tweak the behavior of the software signers, and the way the transaction is finalized at the end. Note that it can’t be guaranteed that every @@ -114,25 +115,35 @@ in this library will.

    }; let finalized = wallet.sign(&mut psbt, SignOptions::default())?; assert!(finalized, "we should have signed all the inputs");
    -

    Return the spending policies for the wallet’s descriptor

    -

    Return the “public” version of the wallet’s descriptor, meaning a new descriptor that has +

    Return the spending policies for the wallet’s descriptor

    +

    Return the “public” version of the wallet’s descriptor, meaning a new descriptor that has the same structure but with every secret key removed

    This can be used to build a watch-only version of a wallet

    -

    Finalize a PSBT, i.e., for each input determine if sufficient data is available to pass +

    Finalize a PSBT, i.e., for each input determine if sufficient data is available to pass validation and construct the respective scriptSig or scriptWitness. Please refer to BIP174 for further information.

    Returns true if the PSBT could be finalized, and false otherwise.

    The SignOptions can be used to tweak the behavior of the finalizer.

    -

    Return the secp256k1 context used for all signing operations

    -

    Returns the descriptor used to create addresses for a particular keychain.

    -

    get the corresponding PSBT Input for a LocalUtxo

    -

    Return an immutable reference to the internal database

    -

    Sync the internal database with the blockchain

    -

    Return the checksum of the public descriptor associated to keychain

    +

    Return the secp256k1 context used for all signing operations

    +

    Returns the descriptor used to create addresses for a particular keychain.

    +

    The derivation index of this wallet. It will return None if it has not derived any addresses. +Otherwise, it will return the index of the highest address it has derived.

    +

    The index of the next address that you would get if you were to ask the wallet for a new address

    +

    Informs the wallet that you no longer intend to broadcast a tx that was built from it.

    +

    This frees up the change address used when creating the tx for use in future transactions.

    +

    get the corresponding PSBT Input for a LocalUtxo

    +

    Return the checksum of the public descriptor associated to keychain

    Internally calls Self::get_descriptor_for_keychain to fetch the right descriptor

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Applies an update to the wallet and stages the changes (but does not commit them).

    +

    Usually you create an update by interacting with some blockchain data source and inserting +transactions related to your wallet into it.

    +

    Commits all curently staged changed to the persistence backend returning and error when this fails.

    +

    Returns the changes that will be staged with the next call to commit.

    +

    Get a reference to the inner TxGraph.

    +

    Get a reference to the inner ChainGraph.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html deleted file mode 100644 index b5fb0318df..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html +++ /dev/null @@ -1,3 +0,0 @@ -get_timestamp in bdk::wallet::time - Rust

    Function bdk::wallet::time::get_timestamp

    source ·
    pub fn get_timestamp() -> u64
    Expand description

    Return the current timestamp in seconds

    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/index.html deleted file mode 100644 index 621edced2c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/index.html +++ /dev/null @@ -1,7 +0,0 @@ -bdk::wallet::time - Rust

    Module bdk::wallet::time

    source ·
    Expand description

    Cross-platform time

    -

    This module provides a function to get the current timestamp that works on all the platforms -supported by the library.

    -

    It can be useful to compare it with the timestamps found in -TransactionDetails.

    -

    Functions

    Return the current timestamp in seconds
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js deleted file mode 100644 index 4568a098c6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"fn":[["get_timestamp","Return the current timestamp in seconds"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html index bb8fa958d5..2b829ccec9 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html @@ -1,5 +1,4 @@ -IsDust in bdk::wallet - Rust

    Trait bdk::wallet::IsDust

    source ·
    pub trait IsDust {
    +IsDust in bdk::wallet - Rust

    Trait bdk::wallet::IsDust

    source ·
    pub trait IsDust {
         fn is_dust(&self, script: &Script) -> bool;
     }
    Expand description

    Trait to check if a value is below the dust limit. We are performing dust value calculation for a given script public key using rust-bitcoin to diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html index 29b958a9d1..c264c91112 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html @@ -1,5 +1,4 @@ -ChangeSpendPolicy in bdk::wallet::tx_builder - Rust

    Variants§

    §

    ChangeAllowed

    Use both change and non-change outputs (default)

    §

    OnlyChange

    Only use change outputs (see TxBuilder::only_spend_change)

    §

    ChangeForbidden

    Only use non-change outputs (see TxBuilder::do_not_spend_change)

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html index 5b2de206bd..12f3f68066 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html @@ -1,5 +1,4 @@ -TxOrdering in bdk::wallet::tx_builder - Rust
    pub enum TxOrdering {
    +TxOrdering in bdk::wallet::tx_builder - Rust
    pub enum TxOrdering {
         Shuffle,
         Untouched,
         Bip69Lexicographic,
    @@ -7,13 +6,13 @@
     

    Variants§

    §

    Shuffle

    Randomized (default)

    §

    Untouched

    Unchanged

    §

    Bip69Lexicographic

    BIP69 / Lexicographic

    -

    Implementations§

    Sort transaction inputs and outputs by TxOrdering variant

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +

    Implementations§

    Sort transaction inputs and outputs by TxOrdering variant

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html index efde794e2f..069020ff57 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html @@ -1,5 +1,4 @@ -bdk::wallet::tx_builder - Rust

    Module bdk::wallet::tx_builder

    source ·
    Expand description

    Transaction builder

    +bdk::wallet::tx_builder - Rust

    Module bdk::wallet::tx_builder

    source ·
    Expand description

    Transaction builder

    Example

    // create a TxBuilder from a wallet
     let mut tx_builder = wallet.build_tx();
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html
    index f3477eed22..e3f933de0f 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html
    @@ -1,7 +1,6 @@
    -BumpFee in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::BumpFee

    source ·
    pub struct BumpFee;
    Expand description

    Marker type to indicate the TxBuilder is being used to bump the fee of an existing transaction.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +BumpFee in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::BumpFee

    source ·
    pub struct BumpFee;
    Expand description

    Marker type to indicate the TxBuilder is being used to bump the fee of an existing transaction.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html index 5730fc311c..49227490d0 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html @@ -1,8 +1,7 @@ -CreateTx in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::CreateTx

    source ·
    pub struct CreateTx;
    Expand description

    Marker type to indicate the TxBuilder is being used to create a new transaction (as opposed +CreateTx in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::CreateTx

    source ·
    pub struct CreateTx;
    Expand description

    Marker type to indicate the TxBuilder is being used to create a new transaction (as opposed to bumping the fee of an existing one).

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html index 25c6744504..af93e9a925 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html @@ -1,5 +1,4 @@ -TxBuilder in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::TxBuilder

    source ·
    pub struct TxBuilder<'a, D, Cs, Ctx> { /* private fields */ }
    Expand description

    A transaction builder

    +TxBuilder in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::TxBuilder

    source ·
    pub struct TxBuilder<'a, D, Cs, Ctx> { /* private fields */ }
    Expand description

    A transaction builder

    A TxBuilder is created by calling build_tx or build_fee_bump on a wallet. After assigning it, you set options on it until finally calling finish to consume the builder and generate the transaction.

    @@ -30,9 +29,9 @@ as in the following example:

    At the moment coin_selection is an exception to the rule as it consumes self. This means it is usually best to call coin_selection on the return value of build_tx before assigning it.

    For further examples see this module’s documentation;

    -

    Implementations§

    Set a custom fee rate

    -

    Set an absolute fee

    -

    Set the policy path to use while creating the transaction for a given keychain.

    +

    Implementations§

    Set a custom fee rate

    +

    Set an absolute fee

    +

    Set the policy path to use while creating the transaction for a given keychain.

    This method accepts a map where the key is the policy node id (see Policy::id) and the value is the list of the indexes of the items that are intended to be satisfied from the policy node (see @@ -76,14 +75,14 @@ path.insert("aabbccdd".to_string(), 50_000) .policy_path(path, KeychainKind::External);

    -

    Add the list of outpoints to the internal list of UTXOs that must be spent.

    +

    Add the list of outpoints to the internal list of UTXOs that must be spent.

    If an error occurs while adding any of the UTXOs then none of them are added and the error is returned.

    These have priority over the “unspendable” utxos, meaning that if a utxo is present both in the “utxos” and the “unspendable” list, it will be spent.

    -

    Add a utxo to the internal list of utxos that must be spent

    +

    Add a utxo to the internal list of utxos that must be spent

    These have priority over the “unspendable” utxos, meaning that if a utxo is present both in the “utxos” and the “unspendable” list, it will be spent.

    -

    Add a foreign UTXO i.e. a UTXO not owned by this wallet.

    +

    Add a foreign UTXO i.e. a UTXO not owned by this wallet.

    At a minimum to add a foreign UTXO we need:

    1. outpoint: To add it to the raw transaction.
    2. @@ -115,56 +114,56 @@ of course check the real input weight matches the expected weight prior to broad

      Note unless you set only_witness_utxo any non-taproot psbt_input you pass to this method must have non_witness_utxo set otherwise you will get an error when finish is called.

      -

    Only spend utxos added by add_utxo.

    +

    Only spend utxos added by add_utxo.

    The wallet will not add additional utxos to the transaction even if they are needed to make the transaction valid.

    -

    Replace the internal list of unspendable utxos with a new list

    +

    Replace the internal list of unspendable utxos with a new list

    It’s important to note that the “must-be-spent” utxos added with TxBuilder::add_utxo have priority over these. See the docs of the two linked methods for more details.

    -

    Add a utxo to the internal list of unspendable utxos

    +

    Add a utxo to the internal list of unspendable utxos

    It’s important to note that the “must-be-spent” utxos added with TxBuilder::add_utxo have priority over this. See the docs of the two linked methods for more details.

    -

    Sign with a specific sig hash

    +

    Sign with a specific sig hash

    Use this option very carefully

    -

    Choose the ordering for inputs and outputs of the transaction

    -

    Use a specific nLockTime while creating the transaction

    +

    Choose the ordering for inputs and outputs of the transaction

    +

    Use a specific nLockTime while creating the transaction

    This can cause conflicts if the wallet’s descriptors contain an “after” (OP_CLTV) operator.

    -

    Build a transaction with a specific version

    +

    Build a transaction with a specific version

    The version should always be greater than 0 and greater than 1 if the wallet’s descriptors contain an “older” (OP_CSV) operator.

    -

    Do not spend change outputs

    +

    Do not spend change outputs

    This effectively adds all the change outputs to the “unspendable” list. See TxBuilder::unspendable.

    -

    Only spend change outputs

    +

    Only spend change outputs

    This effectively adds all the non-change outputs to the “unspendable” list. See TxBuilder::unspendable.

    -

    Only Fill-in the psbt::Input::witness_utxo field when spending from +

    Only Fill-in the psbt::Input::witness_utxo field when spending from SegWit descriptors.

    This reduces the size of the PSBT, but some signers might reject them due to the lack of the non_witness_utxo.

    -

    Fill-in the psbt::Output::redeem_script and +

    Fill-in the psbt::Output::redeem_script and psbt::Output::witness_script fields.

    This is useful for signers which always require it, like ColdCard hardware wallets.

    -

    Fill-in the PSBT_GLOBAL_XPUB field with the extended keys contained in both the external +

    Fill-in the PSBT_GLOBAL_XPUB field with the extended keys contained in both the external and internal descriptors

    This is useful for offline signers that take part to a multisig. Some hardware wallets like BitBox and ColdCard are known to require this.

    -

    Spend all the available inputs. This respects filters like TxBuilder::unspendable and the change policy.

    -

    Choose the coin selection algorithm

    +

    Spend all the available inputs. This respects filters like TxBuilder::unspendable and the change policy.

    +

    Choose the coin selection algorithm

    Overrides the DefaultCoinSelectionAlgorithm.

    Note that this function consumes the builder and returns it so it is usually best to put this as the first call on the builder.

    -

    Finish building the transaction.

    +

    Finish building the transaction.

    Returns the BIP174 “PSBT” and summary details about the transaction.

    -

    Enable signaling RBF

    +

    Enable signaling RBF

    This will use the default nSequence value of 0xFFFFFFFD.

    -

    Enable signaling RBF with a specific nSequence value

    +

    Enable signaling RBF with a specific nSequence value

    This can cause conflicts if the wallet’s descriptors contain an “older” (OP_CSV) operator and the given nsequence is lower than the CSV value.

    If the nsequence is higher than 0xFFFFFFFD an error will be thrown, since it would not be a valid nSequence to signal RBF.

    -

    Set the current blockchain height.

    +

    Set the current blockchain height.

    This will be used to:

    1. Set the nLockTime for preventing fee sniping. @@ -175,12 +174,12 @@ If you want to create a transaction that spends immature coinbase inputs, manual add them using TxBuilder::add_utxos.

    In both cases, if you don’t provide a current height, we use the last sync height.

    -

    Set whether or not the dust limit is checked.

    +

    Set whether or not the dust limit is checked.

    Note: by avoiding a dust limit check you may end up with a transaction that is non-standard.

    -

    Replace the recipients already added with a new list

    -

    Add a recipient to the internal list

    -

    Add data as an output, using OP_RETURN

    -

    Sets the address to drain excess coins to.

    +

    Replace the recipients already added with a new list

    +

    Add a recipient to the internal list

    +

    Add data as an output, using OP_RETURN

    +

    Sets the address to drain excess coins to.

    Usually, when there are excess coins they are sent to a change address generated by the wallet. This option replaces the usual change address with an arbitrary script_pubkey of your choosing. Just as with a change output, if the drain output is not needed (the excess @@ -205,7 +204,7 @@ tx_builder .fee_rate(FeeRate::from_sat_per_vb(5.0)) .enable_rbf(); let (psbt, tx_details) = tx_builder.finish()?;

    -

    Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this +

    Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this script_pubkey in order to bump the transaction fee. Without specifying this the wallet will attempt to find a change output to shrink instead.

    Note that the output may shrink to below the dust limit and therefore be removed. If it is @@ -213,8 +212,8 @@ preserved then it is currently not guaranteed to be in the same position as it w originally.

    Returns an Err if script_pubkey can’t be found among the recipients of the transaction we are bumping.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html index 6d53cb45bd..4aa7544931 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html @@ -1,3 +1,2 @@ -TxBuilderContext in bdk::wallet::tx_builder - Rust
    pub trait TxBuilderContext: Debug + Default + Clone { }
    Expand description

    Context in which the TxBuilder is valid

    -

    Implementors§

    \ No newline at end of file +TxBuilderContext in bdk::wallet::tx_builder - Rust
    pub trait TxBuilderContext: Debug + Default + Clone { }
    Expand description

    Context in which the TxBuilder is valid

    +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/type.Update.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/type.Update.html new file mode 100644 index 0000000000..74b83165d6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/type.Update.html @@ -0,0 +1,3 @@ +Update in bdk::wallet - Rust

    Type Definition bdk::wallet::Update

    source ·
    pub type Update = KeychainScan<KeychainKind, ConfirmationTime>;
    Expand description

    The update to a Wallet used in Wallet::apply_update. This is usually returned from blockchain data sources. +The type parameter T indicates the kind of transaction contained in the update. It’s usually a [bitcoin::Transaction].

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/type.UpdateError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/type.UpdateError.html new file mode 100644 index 0000000000..207646011b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/type.UpdateError.html @@ -0,0 +1,2 @@ +UpdateError in bdk::wallet - Rust

    Type Definition bdk::wallet::UpdateError

    source ·
    pub type UpdateError = UpdateError<ConfirmationTime>;
    Expand description

    Error indicating that something was wrong with an Update<T>.

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/enum.VerifyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/enum.VerifyError.html deleted file mode 100644 index eb4183000e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/enum.VerifyError.html +++ /dev/null @@ -1,18 +0,0 @@ -VerifyError in bdk::wallet::verify - Rust

    Enum bdk::wallet::verify::VerifyError

    source ·
    pub enum VerifyError {
    -    MissingInputTx(Txid),
    -    InvalidInput(OutPoint),
    -    Consensus(Error),
    -    Global(Box<Error>),
    -}
    Available on crate feature verify only.
    Expand description

    Error during validation of a tx agains the consensus rules

    -

    Variants§

    §

    MissingInputTx(Txid)

    The transaction being spent is not available in the database or the blockchain client

    -
    §

    InvalidInput(OutPoint)

    The transaction being spent doesn’t have the requested output

    -
    §

    Consensus(Error)

    Consensus error

    -
    §

    Global(Box<Error>)

    Generic error

    -

    It has to be wrapped in a Box since Error has a variant that contains this enum

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    -

    Calls U::from(self).

    -

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    -
    The alignment of pointer.
    The type for initializers.
    Initializes a with the given initializer. Read more
    Dereferences the given pointer. Read more
    Mutably dereferences the given pointer. Read more
    Drops the object pointed to by the given pointer. Read more
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to -provide by using demand. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/fn.verify_tx.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/fn.verify_tx.html deleted file mode 100644 index fbd973e17d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/fn.verify_tx.html +++ /dev/null @@ -1,8 +0,0 @@ -verify_tx in bdk::wallet::verify - Rust

    Function bdk::wallet::verify::verify_tx

    source ·
    pub fn verify_tx<D: Database, B: GetTx>(
        tx: &Transaction,
        database: &D,
        blockchain: &B
    ) -> Result<(), VerifyError>
    Available on crate feature verify only.
    Expand description

    Verify a transaction against the consensus rules

    -

    This function uses [bitcoinconsensus] to verify transactions by fetching the required data -either from the Database or using the Blockchain.

    -

    Depending on the capabilities of the -Blockchain backend, the method could fail when called with old “historical” transactions or -with unconfirmed transactions that have been evicted from the backend’s memory.

    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/index.html deleted file mode 100644 index 59411028fd..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/index.html +++ /dev/null @@ -1,3 +0,0 @@ -bdk::wallet::verify - Rust

    Module bdk::wallet::verify

    source ·
    Available on crate feature verify only.
    Expand description

    Verify transactions against the consensus rules

    -

    Enums

    Error during validation of a tx agains the consensus rules

    Functions

    Verify a transaction against the consensus rules
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/sidebar-items.js deleted file mode 100644 index c93f31eca0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/verify/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["VerifyError","Error during validation of a tx agains the consensus rules"]],"fn":[["verify_tx","Verify a transaction against the consensus rules"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/all.html new file mode 100644 index 0000000000..851fc3932a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/all.html @@ -0,0 +1 @@ +List of all items in this crate
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/enum.ConfirmationTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/enum.ConfirmationTime.html new file mode 100644 index 0000000000..ca8a813cd5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/enum.ConfirmationTime.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_chain/enum.ConfirmationTime.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/enum.TxHeight.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/enum.TxHeight.html new file mode 100644 index 0000000000..a396dca13c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/enum.TxHeight.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_chain/enum.TxHeight.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/struct.BlockId.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/struct.BlockId.html new file mode 100644 index 0000000000..929197f4db --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/struct.BlockId.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_chain/struct.BlockId.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/struct.FullTxOut.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/struct.FullTxOut.html new file mode 100644 index 0000000000..de66bb3cfc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_data/struct.FullTxOut.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_chain/struct.FullTxOut.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.InsertTxError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.InsertTxError.html new file mode 100644 index 0000000000..a395d28b60 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.InsertTxError.html @@ -0,0 +1,13 @@ +InsertTxError in bdk_chain::chain_graph - Rust
    pub enum InsertTxError<P> {
    +    Chain(InsertTxError<P>),
    +    UnresolvableConflict(UnresolvableConflict<P>),
    +}
    Expand description

    Error that may occur when inserting a transaction.

    +

    Refer to ChainGraph::insert_tx_preview and ChainGraph::insert_tx.

    +

    Variants§

    §

    Chain(InsertTxError<P>)

    §

    UnresolvableConflict(UnresolvableConflict<P>)

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.NewError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.NewError.html new file mode 100644 index 0000000000..03d2c42344 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.NewError.html @@ -0,0 +1,17 @@ +NewError in bdk_chain::chain_graph - Rust
    pub enum NewError<P> {
    +    Conflict {
    +        a: (P, Txid),
    +        b: (P, Txid),
    +    },
    +    Missing(HashSet<Txid>),
    +}
    Expand description

    Error that may occur when calling ChainGraph::new.

    +

    Variants§

    §

    Conflict

    Fields

    §a: (P, Txid)
    §b: (P, Txid)

    Two transactions within the sparse chain conflicted with each other

    +
    §

    Missing(HashSet<Txid>)

    One or more transactions in the chain were not in the graph

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.UpdateError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.UpdateError.html new file mode 100644 index 0000000000..8fecb11a88 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/enum.UpdateError.html @@ -0,0 +1,14 @@ +UpdateError in bdk_chain::chain_graph - Rust
    pub enum UpdateError<P> {
    +    Chain(UpdateError<P>),
    +    UnresolvableConflict(UnresolvableConflict<P>),
    +}
    Expand description

    Represents an update failure.

    +

    Variants§

    §

    Chain(UpdateError<P>)

    The update chain was inconsistent with the existing chain

    +
    §

    UnresolvableConflict(UnresolvableConflict<P>)

    A transaction in the update spent the same input as an already confirmed transaction

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/index.html new file mode 100644 index 0000000000..2bb2b267f6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/index.html @@ -0,0 +1,3 @@ +bdk_chain::chain_graph - Rust

    Module bdk_chain::chain_graph

    source ·
    Expand description

    Module for structures that combine the features of sparse_chain and tx_graph.

    +

    Structs

    A consistent combination of a SparseChain<P> and a TxGraph<T>.
    Represents changes to ChainGraph.
    Represents an unresolvable conflict between an update’s transaction and an +already-confirmed transaction.

    Enums

    Error that may occur when inserting a transaction.
    Error that may occur when calling ChainGraph::new.
    Represents an update failure.

    Type Definitions

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/sidebar-items.js new file mode 100644 index 0000000000..5d5f13a12a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["InsertTxError","Error that may occur when inserting a transaction."],["NewError","Error that may occur when calling [`ChainGraph::new`]."],["UpdateError","Represents an update failure."]],"struct":[["ChainGraph","A consistent combination of a [`SparseChain

    `] and a [`TxGraph`]."],["ChangeSet","Represents changes to [`ChainGraph`]."],["UnresolvableConflict","Represents an unresolvable conflict between an update’s transaction and an already-confirmed transaction."]],"type":[["InsertCheckpointError","A nice alias of [`sparse_chain::InsertCheckpointError`]."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.ChainGraph.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.ChainGraph.html new file mode 100644 index 0000000000..b9bcfb82d0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.ChainGraph.html @@ -0,0 +1,89 @@ +ChainGraph in bdk_chain::chain_graph - Rust

    pub struct ChainGraph<P = TxHeight> { /* private fields */ }
    Expand description

    A consistent combination of a SparseChain<P> and a TxGraph<T>.

    +

    SparseChain only keeps track of transaction ids and their position in the chain but you often +want to store the full transactions as well. Additionally you want to make sure that everything +in the chain is consistent with the full transaction data. ChainGraph enforces these two +invariants:

    +
      +
    1. Every transaction that is in the chain is also in the graph (you always have the full +transaction).
    2. +
    3. No transactions in the chain conflict with each other i.e. they don’t double spend each +other or have ancestors that double spend each other.
    4. +
    +

    Note that the ChainGraph guarantees a 1:1 mapping between transactions in the chain and +graph but not the other way around. Transactions may fall out of the chain (via re-org or +mempool eviction) but will remain in the graph.

    +

    Implementations§

    Returns a reference to the internal SparseChain.

    +

    Returns a reference to the internal TxGraph.

    +

    Create a new chain graph from a chain and a graph.

    +

    There are two reasons this can return an Err:

    +
      +
    1. There is a transaction in the chain that does not have its corresponding full +transaction in graph.
    2. +
    3. The chain has two transactions that allegedly in it but they conflict in the graph +(so could not possibly be in the same chain).
    4. +
    +

    Take an update in the form of a SparseChain<P> and attempt to turn it +into a chain graph by filling in full transactions from self and from new_txs. This +returns a ChainGraph<P, Cow<T>> where the Cow<'a, T> will borrow the transaction if it +got it from self.

    +

    This is useful when interacting with services like an electrum server which returns a list +of txids and heights when calling script_get_history which can easily be inserted into a +SparseChain<TxHeight>. From there you need to figure out which full +transactions you are missing in your chain graph and form new_txs. You then use +inflate_update to turn this into an update ChainGraph<P, Cow<Transaction>> and finally +use determine_changeset to generate the changeset from it.

    +

    Sets the checkpoint limit.

    +

    Refer to SparseChain::checkpoint_limit for more.

    +

    Sets the checkpoint limit.

    +

    Refer to SparseChain::set_checkpoint_limit for more.

    +

    Determines the changes required to invalidate checkpoints from_height (inclusive) and +above. Displaced transactions will have their positions moved to TxHeight::Unconfirmed.

    +

    Invalidate checkpoints from_height (inclusive) and above. Displaced transactions will be +re-positioned to TxHeight::Unconfirmed.

    +

    This is equivalent to calling Self::invalidate_checkpoints_preview and +Self::apply_changeset in sequence.

    +

    Get a transaction that is currently in the underlying SparseChain.

    +

    This does not necessarily mean that it is confirmed in the blockchain, it might just be in +the unconfirmed transaction list within the SparseChain.

    +

    Determines the changes required to insert a transaction into the inner ChainGraph and +SparseChain at the given position.

    +

    If inserting it into the chain position will result in conflicts, the returned +ChangeSet should evict conflicting transactions.

    +

    Inserts [Transaction] at given chain position.

    +

    This is equivalent to calling Self::insert_tx_preview and Self::apply_changeset in +sequence.

    +

    Determines the changes required to insert a [TxOut] into the internal TxGraph.

    +

    Inserts a [TxOut] into the internal TxGraph.

    +

    This is equivalent to calling Self::insert_txout_preview and Self::apply_changeset +in sequence.

    +

    Determines the changes required to insert a block_id (a height and block hash) into the +chain.

    +

    If a checkpoint already exists at that height with a different hash this will return +an error.

    +

    Inserts checkpoint into Self.

    +

    This is equivalent to calling Self::insert_checkpoint_preview and +Self::apply_changeset in sequence.

    +

    Calculates the difference between self and update in the form of a ChangeSet.

    +

    Given a transaction, return an iterator of txids that conflict with it (spends at least +one of the same inputs). This includes all descendants of conflicting transactions.

    +

    This method only returns conflicts that exist in the SparseChain as transactions that +are not included in SparseChain are already considered as evicted.

    +

    Applies changeset to self.

    +

    Warning this method assumes the changeset is assumed to be correctly formed. If it isn’t +then the chain graph may not behave correctly in the future and may panic unexpectedly.

    +

    Applies the update chain graph. Note this is shorthand for calling +Self::determine_changeset() and Self::apply_changeset() in sequence.

    +

    Get the full transaction output at an outpoint if it exists in the chain and the graph.

    +

    Iterate over the full transactions and their position in the chain ordered by their position +in ascending order.

    +

    Finds the transaction in the chain that spends outpoint given the input/output +relationships in graph. Note that the transaction including outpoint does not need to be +in the graph or the chain for this to return Some(_).

    +

    Whether the chain graph contains any data whatsoever.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    The provided closure f will called with each outpoint/txout pair.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.ChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.ChangeSet.html new file mode 100644 index 0000000000..1d19127e02 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.ChangeSet.html @@ -0,0 +1,16 @@ +ChangeSet in bdk_chain::chain_graph - Rust
    pub struct ChangeSet<P> {
    +    pub chain: ChangeSet<P>,
    +    pub graph: Additions,
    +}
    Expand description

    Represents changes to ChainGraph.

    +

    This is essentially a combination of sparse_chain::ChangeSet and tx_graph::Additions.

    +

    Fields§

    §chain: ChangeSet<P>§graph: Additions

    Implementations§

    Returns true if this ChangeSet records no changes.

    +

    Returns true if this ChangeSet contains transaction evictions.

    +

    Appends the changes in other into self such that applying self afterwards has the same +effect as sequentially applying the original self and other.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    The provided closure f will called with each outpoint/txout pair.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.UnresolvableConflict.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.UnresolvableConflict.html new file mode 100644 index 0000000000..ff5a2c8a1f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/struct.UnresolvableConflict.html @@ -0,0 +1,13 @@ +UnresolvableConflict in bdk_chain::chain_graph - Rust
    pub struct UnresolvableConflict<P> {
    +    pub already_confirmed_tx: (P, Txid),
    +    pub update_tx: (P, Txid),
    +}
    Expand description

    Represents an unresolvable conflict between an update’s transaction and an +already-confirmed transaction.

    +

    Fields§

    §already_confirmed_tx: (P, Txid)§update_tx: (P, Txid)

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/type.InsertCheckpointError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/type.InsertCheckpointError.html new file mode 100644 index 0000000000..92f78822bb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/chain_graph/type.InsertCheckpointError.html @@ -0,0 +1,2 @@ +InsertCheckpointError in bdk_chain::chain_graph - Rust
    pub type InsertCheckpointError = InsertCheckpointError;
    Expand description
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/constant.COINBASE_MATURITY.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/constant.COINBASE_MATURITY.html new file mode 100644 index 0000000000..be97a5e42e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/constant.COINBASE_MATURITY.html @@ -0,0 +1,2 @@ +COINBASE_MATURITY in bdk_chain - Rust

    Constant bdk_chain::COINBASE_MATURITY

    source ·
    pub const COINBASE_MATURITY: u32 = 100;
    Expand description

    How many confirmations are needed for a coinbase output to be spent

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/descriptor_ext/trait.DescriptorExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/descriptor_ext/trait.DescriptorExt.html new file mode 100644 index 0000000000..2a275b80dc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/descriptor_ext/trait.DescriptorExt.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_chain/trait.DescriptorExt.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/enum.ConfirmationTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/enum.ConfirmationTime.html new file mode 100644 index 0000000000..70be0a0b08 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/enum.ConfirmationTime.html @@ -0,0 +1,16 @@ +ConfirmationTime in bdk_chain - Rust
    pub enum ConfirmationTime {
    +    Confirmed {
    +        height: u32,
    +        time: u64,
    +    },
    +    Unconfirmed,
    +}
    Expand description

    Block height and timestamp in which a transaction is confirmed in.

    +

    Variants§

    §

    Confirmed

    Fields

    §height: u32
    §time: u64
    §

    Unconfirmed

    Implementations§

    Trait Implementations§

    Get the transaction height of the positon.
    Get the positon’s upper bound of a given height.
    Get the position’s lower bound of a given height.
    Get the unconfirmed position.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/enum.TxHeight.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/enum.TxHeight.html new file mode 100644 index 0000000000..15e397910d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/enum.TxHeight.html @@ -0,0 +1,13 @@ +TxHeight in bdk_chain - Rust

    Enum bdk_chain::TxHeight

    source ·
    pub enum TxHeight {
    +    Confirmed(u32),
    +    Unconfirmed,
    +}
    Expand description

    Represents the height in which a transaction is confirmed at.

    +

    Variants§

    §

    Confirmed(u32)

    §

    Unconfirmed

    Implementations§

    Trait Implementations§

    Get the transaction height of the positon.
    Get the positon’s upper bound of a given height.
    Get the position’s lower bound of a given height.
    Get the unconfirmed position.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/index.html new file mode 100644 index 0000000000..29f9799aef --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/index.html @@ -0,0 +1,18 @@ +bdk_chain - Rust

    Crate bdk_chain

    source ·
    Expand description

    This crate is a collection of core structures for Bitcoin Dev Kit (alpha release).

    +

    The goal of this crate is give wallets the mechanisms needed to:

    +
      +
    1. Figure out what data they need to fetch.
    2. +
    3. Process that data in a way that never leads to inconsistent states.
    4. +
    5. Fully index that data and expose it so that it can be consumed without friction.
    6. +
    +

    Our design goals for these mechanisms are:

    +
      +
    1. Data source agnostic – nothing in bdk_chain cares about where you get data from or whether +you do it synchronously or asynchronously. If you know a fact about the blockchain you can just +tell bdk_chain’s APIs about it and that information will be integrated if it can be done +consistently.
    2. +
    3. Error free APIs.
    4. +
    5. Data persistence agnostic – bdk_chain does not care where you cache on-chain data, what you +cache or how you fetch it.
    6. +
    +

    Re-exports

    pub extern crate serde_crate as serde;
    pub use bitcoin;
    pub use miniscript;

    Modules

    Module for structures that combine the features of sparse_chain and tx_graph.
    Module for keychain based structures.
    Module for structures that maintain sparse (purposely incomplete) snapshots of blockchain data.
    Module for structures that store and traverse transactions.

    Structs

    A reference to a block in the cannonical chain.
    A TxOut with as much data as we can retreive about it
    An index storing TxOuts that have a script pubkey that matches those in a list.

    Enums

    Block height and timestamp in which a transaction is confirmed in.
    Represents the height in which a transaction is confirmed at.

    Constants

    How many confirmations are needed for a coinbase output to be spent

    Traits

    A trait to extend the functionality of a miniscript descriptor.
    Trait to do something with every txout contained in a structure.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/constant.BIP32_MAX_INDEX.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/constant.BIP32_MAX_INDEX.html new file mode 100644 index 0000000000..cace177a79 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/constant.BIP32_MAX_INDEX.html @@ -0,0 +1,2 @@ +BIP32_MAX_INDEX in bdk_chain::keychain - Rust
    pub const BIP32_MAX_INDEX: u32 = _; // 2_147_483_647u32
    Expand description

    Maximum BIP32 derivation index.

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/index.html new file mode 100644 index 0000000000..94acf44ec3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/index.html @@ -0,0 +1,13 @@ +bdk_chain::keychain - Rust

    Module bdk_chain::keychain

    source ·
    Expand description

    Module for keychain based structures.

    +

    A keychain here is a set of application defined indexes for a minscript descriptor where we can +derive script pubkeys at a particular derivation index. The application’s index is simply +anything that implements Ord.

    +

    KeychainTxOutIndex indexes script pubkeys of keychains and scans in relevant outpoints (that +has a txout containing an indexed script pubkey). Internally, this uses SpkTxOutIndex, but +also maintains “revealed” and “lookahead” index count per keychain.

    +

    KeychainTracker combines ChainGraph and KeychainTxOutIndex and enforces atomic +changes between both these structures. KeychainScan is a structure used to update to +KeychainTracker and changes made on a KeychainTracker are reported by +KeychainChangeSets.

    +

    Re-exports

    pub use persist::*;

    Modules

    Persistence for changes made to a KeychainTracker.

    Structs

    Balance differentiated in various categories.
    Represents updates to the derivation index of a KeychainTxOutIndex.
    Represents changes to a KeychainTracker.
    An update that includes the last active indexes of each keychain.
    A convenient combination of a KeychainTxOutIndex and a ChainGraph.
    A convenient wrapper around SpkTxOutIndex that relates script pubkeys to miniscript public +Descriptors.

    Constants

    Maximum BIP32 derivation index.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/index.html new file mode 100644 index 0000000000..edd084cacf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/index.html @@ -0,0 +1,10 @@ +bdk_chain::keychain::persist - Rust

    Module bdk_chain::keychain::persist

    source ·
    Expand description

    Persistence for changes made to a KeychainTracker.

    +

    BDK’s KeychainTracker needs somewhere to persist changes it makes during operation. +Operations like giving out a new address are crucial to persist so that next time the +application is loaded it can find transactions related to that address.

    +

    Note that the KeychainTracker does not read this persisted data during operation since it +always has a copy in memory.

    +

    Structs

    Persist wraps a PersistBackend to create a convenient staging area for changes before they +are persisted. Not all changes made to the KeychainTracker need to be written to disk right +away so you can use Persist::stage to stage it first and then Persist::commit to +finally write it to disk.

    Traits

    A persistence backend for Persist.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/sidebar-items.js new file mode 100644 index 0000000000..9c4f9f3c4a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["Persist","`Persist` wraps a [`PersistBackend`] to create a convenient staging area for changes before they are persisted. Not all changes made to the `KeychainTracker` need to be written to disk right away so you can use [`Persist::stage`] to stage it first and then [`Persist::commit`] to finally write it to disk."]],"trait":[["PersistBackend","A persistence backend for [`Persist`]."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/struct.Persist.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/struct.Persist.html new file mode 100644 index 0000000000..449fe2d614 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/struct.Persist.html @@ -0,0 +1,14 @@ +Persist in bdk_chain::keychain::persist - Rust
    pub struct Persist<K, P, B> { /* private fields */ }
    Expand description

    Persist wraps a PersistBackend to create a convenient staging area for changes before they +are persisted. Not all changes made to the KeychainTracker need to be written to disk right +away so you can use Persist::stage to stage it first and then Persist::commit to +finally write it to disk.

    +

    Implementations§

    Create a new Persist from a PersistBackend.

    +

    Stage a changeset to later persistence with commit.

    +

    Get the changes that haven’t been commited yet

    +

    Commit the staged changes to the underlying persistence backend.

    +

    Retuns a backend defined error if this fails

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/trait.PersistBackend.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/trait.PersistBackend.html new file mode 100644 index 0000000000..ea8d7d5d7a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/persist/trait.PersistBackend.html @@ -0,0 +1,16 @@ +PersistBackend in bdk_chain::keychain::persist - Rust
    pub trait PersistBackend<K, P> {
    +    type WriteError: Debug;
    +    type LoadError: Debug;
    +
    +    fn append_changeset(
            &mut self,
            changeset: &KeychainChangeSet<K, P>
        ) -> Result<(), Self::WriteError>; + fn load_into_keychain_tracker(
            &mut self,
            tracker: &mut KeychainTracker<K, P>
        ) -> Result<(), Self::LoadError>; +}
    Expand description

    A persistence backend for Persist.

    +

    Required Associated Types§

    The error the backend returns when it fails to write.

    +

    The error the backend returns when it fails to load.

    +

    Required Methods§

    Appends a new changeset to the persistance backend.

    +

    It is up to the backend what it does with this. It could store every changeset in a list or +it insert the actual changes to a more structured database. All it needs to guarantee is +that load_into_keychain_tracker restores a keychain tracker to what it should be if all +changesets had been applied sequentially.

    +

    Applies all the changesets the backend has received to tracker.

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/sidebar-items.js new file mode 100644 index 0000000000..1ce48c32e3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":[["BIP32_MAX_INDEX","Maximum BIP32 derivation index."]],"mod":[["persist","Persistence for changes made to a `KeychainTracker`."]],"struct":[["Balance","Balance differentiated in various categories."],["DerivationAdditions","Represents updates to the derivation index of a `KeychainTxOutIndex`."],["KeychainChangeSet","Represents changes to a [`KeychainTracker`]."],["KeychainScan","An update that includes the last active indexes of each keychain."],["KeychainTracker","A convenient combination of a [`KeychainTxOutIndex`] and a [`ChainGraph`]."],["KeychainTxOutIndex","A convenient wrapper around `SpkTxOutIndex` that relates script pubkeys to miniscript public `Descriptor`s."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.Balance.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.Balance.html new file mode 100644 index 0000000000..2354d57817 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.Balance.html @@ -0,0 +1,21 @@ +Balance in bdk_chain::keychain - Rust

    Struct bdk_chain::keychain::Balance

    source ·
    pub struct Balance {
    +    pub immature: u64,
    +    pub trusted_pending: u64,
    +    pub untrusted_pending: u64,
    +    pub confirmed: u64,
    +}
    Expand description

    Balance differentiated in various categories.

    +

    Fields§

    §immature: u64

    All coinbase outputs not yet matured

    +
    §trusted_pending: u64

    Unconfirmed UTXOs generated by a wallet tx

    +
    §untrusted_pending: u64

    Unconfirmed UTXOs received from an external wallet

    +
    §confirmed: u64

    Confirmed and immediately spendable balance

    +

    Implementations§

    Get sum of trusted_pending and confirmed coins.

    +

    This is the balance you can spend right now that shouldn’t get cancelled via another party +double spending it.

    +

    Get the whole balance visible to the wallet.

    +

    Trait Implementations§

    The resulting type after applying the + operator.
    Performs the + operation. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.DerivationAdditions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.DerivationAdditions.html new file mode 100644 index 0000000000..bf82aaf7fd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.DerivationAdditions.html @@ -0,0 +1,15 @@ +DerivationAdditions in bdk_chain::keychain - Rust
    pub struct DerivationAdditions<K>(pub BTreeMap<K, u32>);
    Expand description

    Represents updates to the derivation index of a KeychainTxOutIndex.

    +

    It can be applied to KeychainTxOutIndex with apply_additions. `DerivationAdditions are +monotone in that they will never decrease the revealed derivation index.

    +

    Tuple Fields§

    §0: BTreeMap<K, u32>

    Implementations§

    Returns whether the additions are empty.

    +

    Get the inner map of keychain to its new derivation index.

    +

    Append another DerivationAdditions into self.

    +

    If keychain already exists, increases the index when other’s index > self’s index. +If keychain did not exist, append the new keychain.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainChangeSet.html new file mode 100644 index 0000000000..8d2359eb80 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainChangeSet.html @@ -0,0 +1,17 @@ +KeychainChangeSet in bdk_chain::keychain - Rust
    pub struct KeychainChangeSet<K, P> {
    +    pub derivation_indices: DerivationAdditions<K>,
    +    pub chain_graph: ChangeSet<P>,
    +}
    Expand description

    Represents changes to a KeychainTracker.

    +

    This is essentially a combination of DerivationAdditions and chain_graph::ChangeSet.

    +

    Fields§

    §derivation_indices: DerivationAdditions<K>

    The changes in local keychain derivation indices

    +
    §chain_graph: ChangeSet<P>

    The changes that have occurred in the blockchain

    +

    Implementations§

    Returns whether the KeychainChangeSet is empty (no changes recorded).

    +

    Appends the changes in other into self such that applying self afterwards has the same +effect as sequentially applying the original self and other.

    +

    Note the derivation indices cannot be decreased so other will only change the derivation +index for a keychain if it’s entry is higher than the one in self.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    The provided closure f will called with each outpoint/txout pair.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainScan.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainScan.html new file mode 100644 index 0000000000..1fb3f1baa0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainScan.html @@ -0,0 +1,13 @@ +KeychainScan in bdk_chain::keychain - Rust
    pub struct KeychainScan<K, P> {
    +    pub update: ChainGraph<P>,
    +    pub last_active_indices: BTreeMap<K, u32>,
    +}
    Expand description

    An update that includes the last active indexes of each keychain.

    +

    Fields§

    §update: ChainGraph<P>

    The update data in the form of a chain that could be applied

    +
    §last_active_indices: BTreeMap<K, u32>

    The last active indexes of each keychain

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainTracker.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainTracker.html new file mode 100644 index 0000000000..d1d07df6b8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainTracker.html @@ -0,0 +1,72 @@ +KeychainTracker in bdk_chain::keychain - Rust
    pub struct KeychainTracker<K, P> {
    +    pub txout_index: KeychainTxOutIndex<K>,
    +    /* private fields */
    +}
    Expand description

    A convenient combination of a KeychainTxOutIndex and a ChainGraph.

    +

    The KeychainTracker atomically updates its KeychainTxOutIndex whenever new chain data is +incorporated into its internal ChainGraph.

    +

    Fields§

    §txout_index: KeychainTxOutIndex<K>

    Index between script pubkeys to transaction outputs

    +

    Implementations§

    Add a keychain to the tracker’s txout_index with a descriptor to derive addresses for it. +This is just shorthand for calling KeychainTxOutIndex::add_keychain on the internal +txout_index.

    +

    Adding a keychain means you will be able to derive new script pubkeys under that keychain +and the tracker will discover transaction outputs with those script pubkeys.

    +

    Get the internal map of keychains to their descriptors. This is just shorthand for calling +KeychainTxOutIndex::keychains on the internal txout_index.

    +

    Get the checkpoint limit of the internal SparseChain.

    +

    Refer to SparseChain::checkpoint_limit for more.

    +

    Set the checkpoint limit of the internal SparseChain.

    +

    Refer to SparseChain::set_checkpoint_limit for more.

    +

    Determines the resultant KeychainChangeSet if the given KeychainScan is applied.

    +

    Internally, we call ChainGraph::determine_changeset and also determine the additions of +KeychainTxOutIndex.

    +

    Directly applies a KeychainScan on KeychainTracker.

    +

    This is equivilant to calling determine_changeset and apply_changeset in sequence.

    +

    Applies the changes in changeset to KeychainTracker.

    +

    Internally, this calls KeychainTxOutIndex::apply_additions and +ChainGraph::apply_changeset in sequence.

    +

    Iterates through FullTxOuts that are considered to exist in our representation of the +blockchain/mempool.

    +

    In other words, these are txouts of confirmed and in-mempool transactions, based on our +view of the blockchain/mempool.

    +

    Iterates through FullTxOuts that are unspent outputs.

    +

    Refer to full_txouts for more.

    +

    Returns a reference to the internal ChainGraph.

    +

    Returns a reference to the internal TxGraph (which is part of the ChainGraph).

    +

    Returns a reference to the internal SparseChain (which is part of the ChainGraph).

    +

    Determines the changes as result of inserting block_id (a height and block hash) into the +tracker.

    +

    The caller is responsible for guaranteeing that a block exists at that height. If a +checkpoint already exists at that height with a different hash this will return an error. +Otherwise it will return Ok(true) if the checkpoint didn’t already exist or Ok(false) +if it did.

    +

    Warning: This function modifies the internal state of the tracker. You are responsible +for persisting these changes to disk if you need to restore them.

    +

    Directly insert a block_id into the tracker.

    +

    This is equivalent of calling insert_checkpoint_preview and apply_changeset in +sequence.

    +

    Determines the changes as result of inserting a transaction into the inner ChainGraph +and optionally into the inner chain at position.

    +

    Warning: This function modifies the internal state of the chain graph. You are +responsible for persisting these changes to disk if you need to restore them.

    +

    Directly insert a transaction into the inner ChainGraph and optionally into the inner +chain at position.

    +

    This is equivilant of calling insert_tx_preview and apply_changeset in sequence.

    +

    Returns the balance of the keychain i.e. the value of unspent transaction outputs tracked.

    +

    The caller provides a should_trust predicate which must decide whether the value of +unconfirmed outputs on this keychain are guaranteed to be realized or not. For example:

    +
      +
    • For an internal (change) keychain should_trust should in general be true since even if +you lose an internal output due to eviction you will always gain back the value from whatever output the +unconfirmed transaction was spending (since that output is presumeably from your wallet).
    • +
    • For an external keychain you might want should_trust to return false since someone may cancel (by double spending) +a payment made to addresses on that keychain.
    • +
    +

    When in doubt set should_trust to return false. This doesn’t do anything other than change +where the unconfirmed output’s value is accounted for in Balance.

    +

    Returns the balance of all spendable confirmed unspent outputs of this tracker at a +particular height.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainTxOutIndex.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainTxOutIndex.html new file mode 100644 index 0000000000..791d9847b1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/struct.KeychainTxOutIndex.html @@ -0,0 +1,174 @@ +KeychainTxOutIndex in bdk_chain::keychain - Rust
    pub struct KeychainTxOutIndex<K> { /* private fields */ }
    Expand description

    A convenient wrapper around SpkTxOutIndex that relates script pubkeys to miniscript public +Descriptors.

    +

    Descriptors are referenced by the provided keychain generic (K).

    +

    Script pubkeys for a descriptor are revealed chronologically from index 0. I.e. If the last +revealed index of a descriptor is 5, scripts of indices 0 to 4 are guaranteed to already be +revealed. In addition to revealed scripts, we have a lookahead parameter for each keychain +which defines the number of script pubkeys to store ahead of the last revealed index.

    +

    Methods that could update the last revealed index will return DerivationAdditions to report +these changes. This can be persisted for future recovery.

    +

    Synopsis

    +
    use bdk_chain::keychain::KeychainTxOutIndex;
    +
    +// imagine our service has internal and external addresses but also addresses for users
    +#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
    +enum MyKeychain {
    +    External,
    +    Internal,
    +    MyAppUser {
    +        user_id: u32
    +    }
    +}
    +
    +let mut txout_index = KeychainTxOutIndex::<MyKeychain>::default();
    +
    +txout_index.add_keychain(MyKeychain::External, external_descriptor);
    +txout_index.add_keychain(MyKeychain::Internal, internal_descriptor);
    +txout_index.add_keychain(MyKeychain::MyAppUser { user_id: 42 }, descriptor_for_user_42);
    +
    +let new_spk_for_user = txout_index.reveal_next_spk(&MyKeychain::MyAppUser{ user_id: 42 });
    +

    Implementations§

    Scans an object for relevant outpoints, which are stored and indexed internally.

    +

    If the matched script pubkey is part of the lookahead, the last stored index is updated for +the script pubkey’s keychain and the DerivationAdditions returned will reflect the +change.

    +

    Typically this method is used in two situations:

    +
      +
    1. After loading transaction data from disk you may scan over all the txouts to restore all +your txouts.
    2. +
    3. When getting new data from the chain you usually scan it before incorporating it into +your chain state (i.e. SparseChain, ChainGraph).
    4. +
    +

    See ForEachTxout for the types that support this.

    +

    Scan a single outpoint for a matching script pubkey.

    +

    If it matches the index will store and index it.

    +

    Return a reference to the internal SpkTxOutIndex.

    +

    Return a reference to the internal map of keychain to descriptors.

    +

    Add a keychain to the tracker’s txout_index with a descriptor to derive addresses for it.

    +

    Adding a keychain means you will be able to derive new script pubkeys under that keychain +and the txout index will discover transaction outputs with those script pubkeys.

    +
    Panics
    +

    This will panic if a different descriptor is introduced to the same keychain.

    +

    Return the lookahead setting for each keychain.

    +

    Refer to set_lookahead for a deeper explanation on lookahead.

    +

    Convenience method to call set_lookahead for all keychains.

    +

    Set the lookahead count for keychain.

    +

    The lookahead is the number of scripts to cache ahead of the last stored script index. This +is useful during a scan via scan or scan_txout.

    +
    Panics
    +

    This will panic if keychain does not exist.

    +

    Convenience method to call lookahead_to_target for multiple keychains.

    +

    Store lookahead scripts until target_index.

    +

    This does not change the lookahead setting.

    +

    Generates script pubkey iterators for every keychain. The iterators iterate over all +derivable script pubkeys.

    +

    Generates a script pubkey iterator for the given keychain’s descriptor (if exists). The +iterator iterates over all derivable scripts of the keychain’s descriptor.

    +
    Panics
    +

    This will panic if keychain does not exist.

    +

    Convenience method to get revealed_spks_of_keychain of all keychains.

    +

    Iterates over the script pubkeys revealed by this index under keychain.

    +

    Get the next derivation index for keychain. This is the index after the last revealed +derivation index.

    +

    The second field in the returned tuple represents whether the next derivation index is new. +There are two scenarios where the next derivation index is reused (not new):

    +
      +
    1. The keychain’s descriptor has no wildcard, and a script has already been revealed.
    2. +
    3. The number of revealed scripts has already reached 2^31 (refer to BIP-32).
    4. +
    +

    Not checking the second field of the tuple may result in address reuse.

    +
    Panics
    +

    Panics if the keychain does not exist.

    +

    Get the last derivation index that is revealed for each keychain.

    +

    Keychains with no revealed indices will not be included in the returned BTreeMap.

    +

    Get the last derivation index revealed for keychain.

    +

    Convenience method to call Self::reveal_to_target on multiple keychains.

    +

    Reveals script pubkeys of the keychain’s descriptor up to and including the +target_index.

    +

    If the target_index cannot be reached (due to the descriptor having no wildcard, and/or +the target_index is in the hardened index range), this method will do a best-effort and +reveal up to the last possible index.

    +

    This returns an iterator of newly revealed indices (along side their scripts), and a +DerivationAdditions which reports updates to the latest revealed index. If no new script +pubkeys are revealed, both of these will be empty.

    +
    Panics
    +

    Panics if keychain does not exist.

    +

    Attempts to reveal the next script pubkey for keychain.

    +

    Returns the derivation index of the revealed script pubkey, the revealed script pubkey and a +DerivationAdditions which represents changes in the last revealed index (if any).

    +

    When a new script cannot be revealed, we return the last revealed script and an empty +DerivationAdditions. There are two scenarios when a new script pubkey cannot be derived:

    +
      +
    1. The descriptor has no wildcard and already has one script revealed.
    2. +
    3. The descriptor has already revealed scripts up to the numeric bound.
    4. +
    +
    Panics
    +

    Panics if the keychain does not exist.

    +

    Gets the next unused script pubkey in the keychain. I.e. the script pubkey with the lowest +index that has not been used yet.

    +

    This will derive and reveal a new script pubkey if no more unused script pubkeys exist.

    +

    If the descriptor has no wildcard and already has a used script pubkey, or if a descriptor +has used all scripts up to the derivation bounds, the last derived script pubkey will be +returned.

    +
    Panics
    +

    Panics if keychain has never been added to the index

    +

    Marks the script pubkey at index as used even though it hasn’t seen an output with it. +This only has an effect when the index had been added to self already and was unused.

    +

    Returns whether the index was originally present as unused.

    +

    This is useful when you want to reserve a script pubkey for something but don’t want to add +the transaction output using it to the index yet. Other callers will consider index on +keychain used until you call unmark_used.

    +

    Undoes the effect of mark_used. Returns whether the index is inserted back into +unused.

    +

    Note that if self has scanned an output with this script pubkey then this will have no +effect.

    +

    Iterates over all unused script pubkeys for a keychain that have been stored in the index.

    +

    Iterates over all the [OutPoint] that have a TxOut with a script pubkey derived from +keychain.

    +

    Returns the highest derivation index of the keychain where KeychainTxOutIndex has +found a [TxOut] with it’s script pubkey.

    +

    Returns the highest derivation index of each keychain that KeychainTxOutIndex has found +a [TxOut] with it’s script pubkey.

    +

    Applies the derivation additions to the KeychainTxOutIndex, extending the number of +derived scripts per keychain, as specified in the additions.

    +

    Methods from Deref<Target = SpkTxOutIndex<(K, u32)>>§

    Iterate over all known txouts that spend to tracked script pubkeys.

    +

    Finds all txouts on a transaction that has previously been scanned and indexed.

    +

    Iterates over all outputs with script pubkeys in an index range.

    +

    Returns the txout and script pubkey index of the TxOut at OutPoint.

    +

    Returns None if the TxOut hasn’t been scanned or if nothing matching was found there.

    +

    Returns the script that has been inserted at the index.

    +

    If that index hasn’t been inserted yet it will return None.

    +

    The script pubkeys being tracked by the index.

    +

    Iterates over a unused script pubkeys in a index range.

    +

    Here “unused” means that after the script pubkey was stored in the index, the index has +never scanned a transaction output with it.

    +
    Example
    +
    
    +// imagine our spks are indexed like (keychain, derivation_index).
    +let txout_index = SpkTxOutIndex::<(u32, u32)>::default();
    +let all_unused_spks = txout_index.unused_spks(..);
    +let change_index = 1;
    +let unused_change_spks =
    +    txout_index.unused_spks((change_index, u32::MIN)..(change_index, u32::MAX));
    +

    Returns whether the script pubkey at index has been used or not.

    +

    Here “unused” means that after the script pubkey was stored in the index, the index has +never scanned a transaction output with it.

    +

    Returns the index associated with the script pubkey.

    +

    Computes total input value going from script pubkeys in the index (sent) and total output +value going to script pubkeys in the index (received) in tx. For the sent to be computed +correctly the output being spent must have already been scanned by the index. Calculating +received just uses the transaction outputs directly so will be correct even if it has not +been scanned.

    +

    Computes the net value that this transaction gives to the script pubkeys in the index and +takes from the transaction outputs in the index. Shorthand for calling +sent_and_received and subtracting sent from received.

    +

    Whether any of the inputs of this transaction spend a txout tracked or whether any output +matches one of our script pubkeys.

    +

    It is easily possible to misuse this method and get false negatives by calling it before you +have scanned the TxOuts the transaction is spending. For example if you want to filter out +all the transactions in a block that are irrelevant you must first scan all the +transactions in the block and only then use this method.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    The resulting type after dereferencing.
    Dereferences the value.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/tracker/struct.KeychainTracker.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/tracker/struct.KeychainTracker.html new file mode 100644 index 0000000000..01e1089f7e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/tracker/struct.KeychainTracker.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../../bdk_chain/keychain/struct.KeychainTracker.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/txout_index/constant.BIP32_MAX_INDEX.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/txout_index/constant.BIP32_MAX_INDEX.html new file mode 100644 index 0000000000..fa2b902399 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/txout_index/constant.BIP32_MAX_INDEX.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../../bdk_chain/keychain/constant.BIP32_MAX_INDEX.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/txout_index/struct.KeychainTxOutIndex.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/txout_index/struct.KeychainTxOutIndex.html new file mode 100644 index 0000000000..25a8ee11d9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/keychain/txout_index/struct.KeychainTxOutIndex.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../../bdk_chain/keychain/struct.KeychainTxOutIndex.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sidebar-items.js new file mode 100644 index 0000000000..b05c084a29 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":[["COINBASE_MATURITY","How many confirmations are needed for a coinbase output to be spent"]],"enum":[["ConfirmationTime","Block height and timestamp in which a transaction is confirmed in."],["TxHeight","Represents the height in which a transaction is confirmed at."]],"externcrate":[["serde",""]],"mod":[["chain_graph","Module for structures that combine the features of [`sparse_chain`] and [`tx_graph`]."],["keychain","Module for keychain based structures."],["sparse_chain","Module for structures that maintain sparse (purposely incomplete) snapshots of blockchain data."],["tx_graph","Module for structures that store and traverse transactions."]],"struct":[["BlockId","A reference to a block in the cannonical chain."],["FullTxOut","A `TxOut` with as much data as we can retreive about it"],["SpkTxOutIndex","An index storing `TxOut`s that have a script pubkey that matches those in a list."]],"trait":[["DescriptorExt","A trait to extend the functionality of a miniscript descriptor."],["ForEachTxOut","Trait to do something with every txout contained in a structure."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.InsertCheckpointError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.InsertCheckpointError.html new file mode 100644 index 0000000000..0dd477e41b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.InsertCheckpointError.html @@ -0,0 +1,16 @@ +InsertCheckpointError in bdk_chain::sparse_chain - Rust
    pub enum InsertCheckpointError {
    +    HashNotMatching {
    +        height: u32,
    +        original_hash: BlockHash,
    +        update_hash: BlockHash,
    +    },
    +}
    Expand description

    Represents a failure when trying to insert a checkpoint into SparseChain.

    +

    Variants§

    §

    HashNotMatching

    Fields

    §height: u32
    §original_hash: BlockHash
    §update_hash: BlockHash

    Occurs when checkpoint of the same height already exists with a different [BlockHash].

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.InsertTxError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.InsertTxError.html new file mode 100644 index 0000000000..c4e829be0d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.InsertTxError.html @@ -0,0 +1,23 @@ +InsertTxError in bdk_chain::sparse_chain - Rust
    pub enum InsertTxError<P> {
    +    TxTooHigh {
    +        txid: Txid,
    +        tx_height: u32,
    +        tip_height: Option<u32>,
    +    },
    +    TxMovedUnexpectedly {
    +        txid: Txid,
    +        original_pos: P,
    +        update_pos: P,
    +    },
    +}
    Expand description

    Represents a failure when trying to insert a [Txid] into SparseChain.

    +

    Variants§

    §

    TxTooHigh

    Fields

    §txid: Txid
    §tx_height: u32
    §tip_height: Option<u32>

    Occurs when the [Txid] is to be inserted at a hight higher than the SparseChain’s tip.

    +
    §

    TxMovedUnexpectedly

    Fields

    §txid: Txid
    §original_pos: P
    §update_pos: P

    Occurs when the [Txid] is already in the SparseChain and the insertion would result in +an unexpected move in ChainPosition.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.UpdateError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.UpdateError.html new file mode 100644 index 0000000000..85281b5c08 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/enum.UpdateError.html @@ -0,0 +1,21 @@ +UpdateError in bdk_chain::sparse_chain - Rust
    pub enum UpdateError<P = TxHeight> {
    +    NotConnected(u32),
    +    TxInconsistent {
    +        txid: Txid,
    +        original_pos: P,
    +        update_pos: P,
    +    },
    +}
    Expand description

    Represents an update failure of SparseChain.

    +

    Variants§

    §

    NotConnected(u32)

    The update cannot be applied to the chain because the chain suffix it represents did not +connect to the existing chain. This error case contains the checkpoint height to include so +that the chains can connect.

    +
    §

    TxInconsistent

    Fields

    §txid: Txid
    §original_pos: P
    §update_pos: P

    The update contains inconsistent tx states (e.g. it changed the transaction’s height). This +error is usually the inconsistency found.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/index.html new file mode 100644 index 0000000000..bc751eb0b1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/index.html @@ -0,0 +1,266 @@ +bdk_chain::sparse_chain - Rust

    Module bdk_chain::sparse_chain

    source ·
    Expand description

    Module for structures that maintain sparse (purposely incomplete) snapshots of blockchain data.

    +

    SparseChain stores [Txid]s ordered by an index that implements ChainPosition (this +represents the transaction’s position in the blockchain, by default TxHeight is used). +SparseChain also contains “checkpoints” which relate block height to block hash. Changes to +a SparseChain are reported by returning ChangeSets.

    +

    Updating SparseChain

    +

    A sparsechain can be thought of as a consistent snapshot of history. A SparseChain can be +updated by applying an update SparseChain on top, but only if they “connect” via their +checkpoints and don’t result in unexpected movements of transactions.

    + +
    // create empty sparsechain
    +let mut chain = SparseChain::<TxHeight>::default();
    +
    +/* Updating an empty sparsechain will always succeed */
    +
    +let update = SparseChain::from_checkpoints(vec![
    +    BlockId {
    +        height: 1,
    +        hash: hash_a,
    +    },
    +    BlockId {
    +        height: 2,
    +        hash: hash_b,
    +    },
    +]);
    +let _ = chain
    +    .apply_update(update)
    +    .expect("updating an empty sparsechain will always succeed");
    +
    +/* To update a non-empty sparsechain, the update must connect */
    +
    +let update = SparseChain::from_checkpoints(vec![
    +    BlockId {
    +        height: 2,
    +        hash: hash_b,
    +    },
    +    BlockId {
    +        height: 3,
    +        hash: hash_c,
    +    },
    +]);
    +let _ = chain
    +    .apply_update(update)
    +    .expect("we have connected at block height 2, so this must succeed");
    +

    Invalid updates

    +

    As shown above, sparsechains can be “connected” by comparing their checkpoints. However, there +are situations where two sparsechains cannot connect in a way that guarantees consistency.

    + +
    // our sparsechain has 2 checkpoints
    +let chain = SparseChain::<TxHeight>::from_checkpoints(vec![
    +    BlockId {
    +        height: 1,
    +        hash: hash_a,
    +    },
    +    BlockId {
    +        height: 2,
    +        hash: hash_b,
    +    },
    +]);
    +
    +/* Example of an ambiguous update that does not fully connect */
    +
    +let ambiguous_update = SparseChain::from_checkpoints(vec![
    +    // the update sort of "connects" at checkpoint 1, but...
    +    BlockId {
    +        height: 1,
    +        hash: hash_a,
    +    },
    +    // we cannot determine whether checkpoint 3 connects with checkpoint 2
    +    BlockId {
    +        height: 3,
    +        hash: hash_c,
    +    },
    +]);
    +let _ = chain
    +    .determine_changeset(&ambiguous_update)
    +    .expect_err("cannot apply ambiguous update");
    +
    +/* Example of an update that completely misses the point */
    +
    +let disconnected_update = SparseChain::from_checkpoints(vec![
    +    // the last checkpoint in chain is 2, so 3 and 4 do not connect
    +    BlockId {
    +        height: 3,
    +        hash: hash_c,
    +    },
    +    BlockId {
    +        height: 4,
    +        hash: hash_d,
    +    },
    +]);
    +let _ = chain
    +    .determine_changeset(&disconnected_update)
    +    .expect_err("cannot apply a totally-disconnected update");
    +

    Handling reorgs

    +

    Updates can be formed to evict data from the original sparsechain. This is useful for handling +blockchain reorgs.

    + +
    // our chain has a single checkpoint at height 11
    +let mut chain = SparseChain::<TxHeight>::from_checkpoints(vec![BlockId {
    +    height: 11,
    +    hash: hash_a,
    +}]);
    +
    +// we detect a reorg at height 11, and we introduce a new checkpoint at height 12
    +let update = SparseChain::from_checkpoints(vec![
    +    BlockId {
    +        height: 11,
    +        hash: hash_b,
    +    },
    +    BlockId {
    +        height: 12,
    +        hash: hash_c,
    +    },
    +]);
    +let _ = chain
    +    .apply_update(update)
    +    .expect("we can evict/replace checkpoint 11 since it is the only checkpoint");
    +
    +// now our `chain` has 2 checkpoints (11:hash_b & 12:hash_c)
    +// we detect another reorg, this time at height 12...
    +let update = SparseChain::from_checkpoints(vec![
    +    // we connect at checkpoint 11 as this is our "point of agreement"
    +    BlockId {
    +        height: 11,
    +        hash: hash_b,
    +    },
    +    BlockId {
    +        height: 12,
    +        hash: hash_d,
    +    },
    +]);
    +let _ = chain
    +    .apply_update(update)
    +    .expect("we have provided a valid point of agreement, so our reorg update will succeed");
    +

    Movement of transactions during update

    +

    If the original sparsechain and update sparsechain contain the same transaction at different +ChainPositions, the transaction is considered as “moved”. There are various movements of a +transaction that are invalid and update will fail.

    +

    Valid movements:

    +
      +
    • When the transaction moved from unconfirmed (in original) to confirmed (in update). In other +words, confirming transactions are allowed!
    • +
    • If there has been a reorg at height x, an originally confirmed transaction at height x or +above, may move to another height (that is at x or above, including becoming unconfirmed).
    • +
    +

    Invalid movements:

    +
      +
    • A confirmed transaction cannot move without a reorg.
    • +
    • Even with a reorg, an originally confirmed transaction cannot be moved below the height of the +reorg.
    • +
    +

    Custom ChainPosition

    +

    SparseChain maintains a list of txids ordered by ChainPosition. By default, TxHeight +is used, however additional data can be incorporated into the implementation.

    +

    For example, we can have “perfect ordering” of transactions if our positional index is a +combination of block height and transaction position in block.

    + +
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
    +pub enum TxPosition {
    +    Confirmed {
    +        height: u32,   // height of block
    +        position: u32, // position of transaction in the block
    +    },
    +    Unconfirmed,
    +}
    +
    +impl Default for TxPosition {
    +    fn default() -> Self {
    +        Self::Unconfirmed
    +    }
    +}
    +
    +impl ChainPosition for TxPosition {
    +    fn height(&self) -> TxHeight {
    +        match self {
    +            Self::Confirmed { height, .. } => TxHeight::Confirmed(*height),
    +            Self::Unconfirmed => TxHeight::Unconfirmed,
    +        }
    +    }
    +
    +    fn max_ord_of_height(height: TxHeight) -> Self {
    +        match height {
    +            TxHeight::Confirmed(height) => Self::Confirmed {
    +                height,
    +                position: u32::MAX,
    +            },
    +            TxHeight::Unconfirmed => Self::Unconfirmed,
    +        }
    +    }
    +
    +    fn min_ord_of_height(height: TxHeight) -> Self {
    +        match height {
    +            TxHeight::Confirmed(height) => Self::Confirmed {
    +                height,
    +                position: u32::MIN,
    +            },
    +            TxHeight::Unconfirmed => Self::Unconfirmed,
    +        }
    +    }
    +}
    +
    +let mut chain = SparseChain::<TxPosition>::default();
    +let _ = chain
    +    .insert_checkpoint(BlockId {
    +        height: 10,
    +        hash: hash_a,
    +    })
    +    .unwrap();
    +let _ = chain
    +    .insert_tx(
    +        txid_1,
    +        TxPosition::Confirmed {
    +            height: 9,
    +            position: 4321,
    +        },
    +    )
    +    .unwrap();
    +let _ = chain
    +    .insert_tx(
    +        txid_2,
    +        TxPosition::Confirmed {
    +            height: 9,
    +            position: 1234,
    +        },
    +    )
    +    .unwrap();
    +let _ = chain
    +    .insert_tx(
    +        txid_3,
    +        TxPosition::Confirmed {
    +            height: 10,
    +            position: 321,
    +        },
    +    )
    +    .unwrap();
    +
    +// transactions are ordered correctly
    +assert_eq!(
    +    chain.txids().collect::<Vec<_>>(),
    +    vec![
    +        &(
    +            TxPosition::Confirmed {
    +                height: 9,
    +                position: 1234
    +            },
    +            txid_2
    +        ),
    +        &(
    +            TxPosition::Confirmed {
    +                height: 9,
    +                position: 4321
    +            },
    +            txid_1
    +        ),
    +        &(
    +            TxPosition::Confirmed {
    +                height: 10,
    +                position: 321
    +            },
    +            txid_3
    +        ),
    +    ],
    +);
    +

    Structs

    The return value of determine_changeset.
    This is a non-monotone structure that tracks relevant [Txid]s that are ordered by chain +position P.

    Enums

    Represents a failure when trying to insert a checkpoint into SparseChain.
    Represents a failure when trying to insert a [Txid] into SparseChain.
    Represents an update failure of SparseChain.

    Traits

    Represents an position in which transactions are ordered in SparseChain.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/sidebar-items.js new file mode 100644 index 0000000000..0872de8708 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["InsertCheckpointError","Represents a failure when trying to insert a checkpoint into [`SparseChain`]."],["InsertTxError","Represents a failure when trying to insert a [`Txid`] into [`SparseChain`]."],["UpdateError","Represents an update failure of [`SparseChain`]."]],"struct":[["ChangeSet","The return value of `determine_changeset`."],["SparseChain","This is a non-monotone structure that tracks relevant [`Txid`]s that are ordered by chain position `P`."]],"trait":[["ChainPosition","Represents an position in which transactions are ordered in [`SparseChain`]."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/struct.ChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/struct.ChangeSet.html new file mode 100644 index 0000000000..9f81a5c315 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/struct.ChangeSet.html @@ -0,0 +1,14 @@ +ChangeSet in bdk_chain::sparse_chain - Rust
    pub struct ChangeSet<P = TxHeight> {
    +    pub checkpoints: BTreeMap<u32, Option<BlockHash>>,
    +    pub txids: BTreeMap<Txid, Option<P>>,
    +}
    Expand description

    The return value of determine_changeset.

    +

    Fields§

    §checkpoints: BTreeMap<u32, Option<BlockHash>>§txids: BTreeMap<Txid, Option<P>>

    Implementations§

    Appends the changes in other into self such that applying self afterwards has the same +effect as sequentially applying the original self and other.

    +

    Whether this changeset contains no changes.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/struct.SparseChain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/struct.SparseChain.html new file mode 100644 index 0000000000..9ff0e1f174 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/struct.SparseChain.html @@ -0,0 +1,76 @@ +SparseChain in bdk_chain::sparse_chain - Rust
    pub struct SparseChain<P = TxHeight> { /* private fields */ }
    Expand description

    This is a non-monotone structure that tracks relevant [Txid]s that are ordered by chain +position P.

    +

    We use [BlockHash]s alongside their chain height as “checkpoints” to enforce consistency.

    +

    To “merge” two SparseChains, the ChangeSet can be calculated by calling +determine_changeset and applying the ChangeSet via apply_changeset. For convenience, +apply_update does the above two steps in one call.

    +

    Refer to module-level documentation for more.

    +

    Implementations§

    Creates a new chain from a list of block hashes and heights. The caller must guarantee they +are in the same chain.

    +

    Get the checkpoint for the last known tip.

    +

    Get the checkpoint at the given height if it exists.

    +

    Return the ChainPosition of a txid.

    +

    This returns None if the transation does not exist.

    +

    Return a BTreeMap of all checkpoints (block hashes by height).

    +

    Return an iterator over checkpoints in a height range, in ascending height order.

    +

    Preview changes of updating Self with another chain that connects to it.

    +

    If the update wishes to introduce confirmed transactions, it must contain a checkpoint +that is exactly the same height as one of self’s checkpoints.

    +

    To invalidate from a given checkpoint, update must contain a checkpoint of the same height +but different hash. Invalidated checkpoints result in invalidated transactions becoming +“unconfirmed”.

    +

    An error will be returned if an update will result in inconsistencies or if the update does +not properly connect with self.

    +

    Refer to module-level documentation for more.

    +

    Updates SparseChain with another chain that connects to it.

    +

    This is equivilant to calling determine_changeset and apply_changeset in sequence.

    +

    Derives a ChangeSet that assumes that there are no preceding changesets.

    +

    The changeset returned will record additions of all [Txid]s and checkpoints included in +Self.

    +

    Determines the ChangeSet when checkpoints from_height (inclusive) and above are +invalidated. Displaced [Txid]s will be repositioned to TxHeight::Unconfirmed.

    +

    Invalidate checkpoints from_height (inclusive) and above.

    +

    This is equivalent to calling invalidate_checkpoints_preview and apply_changeset in +sequence.

    +

    Determines the ChangeSet when all transactions of height TxHeight::Unconfirmed are +removed completely.

    +

    Clears all transactions of height TxHeight::Unconfirmed.

    +

    This is equivalent to calling clear_mempool_preview and apply_changeset in sequence.

    +

    ChangeSet.

    +

    Determines the resultant ChangeSet if [Txid] was inserted at position pos.

    +

    Changes to the [Txid]’s position is allowed (under the rules noted in +module-level documentation) and will be reflected in the ChangeSet.

    +

    Inserts a given [Txid] at pos.

    +

    This is equivilant to calling insert_tx_preview and apply_changeset in sequence.

    +

    Determines the resultant ChangeSet if BlockId was inserted.

    +

    If the change would result in a change in block hash of a certain height, insertion would +fail.

    +

    Insert a checkpoint (BlockId).

    +

    This is equivilant to calling insert_checkpoint_preview and apply_changeset in +sequence.

    +

    Iterate over all [Txid]s ordered by their ChainPosition.

    +

    Iterate over a sub-range of positioned [Txid]s.

    +

    Iterate over a sub-range of positioned [Txid]s, where the range is defined by +ChainPosition only.

    +

    Iterate over a sub-range of positioned [Txid]s, where the range is define by TxHeight +only.

    +

    Attempt to retrieve a FullTxOut of the given outpoint.

    +

    This will return Some only if the output’s transaction is in both self and graph.

    +

    Returns the value set as the checkpoint limit.

    +

    Refer to set_checkpoint_limit.

    +

    Set the checkpoint limit.

    +

    The checkpoint limit restricts the number of checkpoints that can be stored in Self. +Oldest checkpoints are pruned first.

    +

    Return [Txid]s that would be added to the sparse chain if this changeset was applied.

    +

    Finds the transaction in the chain that spends outpoint.

    +

    TxGraph is used to provide the spend relationships.

    +

    Note that the transaction including outpoint does not need to be in the graph or the +chain for this to return Some.

    +

    Returns whether the sparse chain contains any checkpoints or transactions.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/trait.ChainPosition.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/trait.ChainPosition.html new file mode 100644 index 0000000000..b1437e14cf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/sparse_chain/trait.ChainPosition.html @@ -0,0 +1,13 @@ +ChainPosition in bdk_chain::sparse_chain - Rust
    pub trait ChainPosition: Debug + Clone + Eq + PartialOrd + Ord + Hash + Send + Sync + 'static {
    +    fn height(&self) -> TxHeight;
    +    fn max_ord_of_height(height: TxHeight) -> Self;
    +    fn min_ord_of_height(height: TxHeight) -> Self;
    +
    +    fn unconfirmed() -> Self { ... }
    +}
    Expand description

    Represents an position in which transactions are ordered in SparseChain.

    +

    ChainPosition implementations must be Ord by TxHeight first.

    +

    Required Methods§

    Get the transaction height of the positon.

    +

    Get the positon’s upper bound of a given height.

    +

    Get the position’s lower bound of a given height.

    +

    Provided Methods§

    Get the unconfirmed position.

    +

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/spk_txout_index/struct.SpkTxOutIndex.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/spk_txout_index/struct.SpkTxOutIndex.html new file mode 100644 index 0000000000..ed0bb79c2a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/spk_txout_index/struct.SpkTxOutIndex.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_chain/struct.SpkTxOutIndex.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.BlockId.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.BlockId.html new file mode 100644 index 0000000000..b50bae278b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.BlockId.html @@ -0,0 +1,15 @@ +BlockId in bdk_chain - Rust

    Struct bdk_chain::BlockId

    source ·
    pub struct BlockId {
    +    pub height: u32,
    +    pub hash: BlockHash,
    +}
    Expand description

    A reference to a block in the cannonical chain.

    +

    Fields§

    §height: u32

    The height the block was confirmed at

    +
    §hash: BlockHash

    The hash of the block

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.FullTxOut.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.FullTxOut.html new file mode 100644 index 0000000000..26cc2f88d8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.FullTxOut.html @@ -0,0 +1,22 @@ +FullTxOut in bdk_chain - Rust

    Struct bdk_chain::FullTxOut

    source ·
    pub struct FullTxOut<I> {
    +    pub outpoint: OutPoint,
    +    pub txout: TxOut,
    +    pub chain_position: I,
    +    pub spent_by: Option<(I, Txid)>,
    +    pub is_on_coinbase: bool,
    +}
    Expand description

    A TxOut with as much data as we can retreive about it

    +

    Fields§

    §outpoint: OutPoint

    The location of the TxOut

    +
    §txout: TxOut

    The TxOut

    +
    §chain_position: I

    The position of the transaction in outpoint in the overall chain.

    +
    §spent_by: Option<(I, Txid)>

    The txid and chain position of the transaction (if any) that has spent this output.

    +
    §is_on_coinbase: bool

    Whether this output is on a coinbase transaction

    +

    Implementations§

    Whether the utxo is/was/will be spendable at height.

    +

    It is spendable if it is not an immature coinbase output and no spending tx has been +confirmed by that heigt.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.SpkTxOutIndex.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.SpkTxOutIndex.html new file mode 100644 index 0000000000..e7d9c40406 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/struct.SpkTxOutIndex.html @@ -0,0 +1,75 @@ +SpkTxOutIndex in bdk_chain - Rust

    Struct bdk_chain::SpkTxOutIndex

    source ·
    pub struct SpkTxOutIndex<I> { /* private fields */ }
    Expand description

    An index storing TxOuts that have a script pubkey that matches those in a list.

    +

    The basic idea is that you insert script pubkeys you care about into the index with +insert_spk and then when you call scan the index will look at any txouts you pass in and +store and index any txouts matching one of its script pubkeys.

    +

    Each script pubkey is associated with a application defined index script index I which must be +Ord. Usually this is used to associate the derivation index of the script pubkey or even a +combination of (keychain, derivation_index).

    +

    Note there is no harm in scanning transactions that disappear from the blockchain or were never +in there in the first place. SpkTxOutIndex is intentionally monotone – you cannot delete or +modify txouts that have been indexed. To find out which txouts from the index are actually in the +chain or unspent etc you must use other sources of information like a SparseChain.

    +

    Implementations§

    Scans an object containing many txouts.

    +

    Typically this is used in two situations:

    +
      +
    1. After loading transaction data from disk you may scan over all the txouts to restore all +your txouts.
    2. +
    3. When getting new data from the chain you usually scan it before incorporating it into your chain state.
    4. +
    +

    See ForEachTxout for the types that support this.

    +

    Scan a single TxOut for a matching script pubkey, and returns the index that matched the +script pubkey (if any).

    +

    Iterate over all known txouts that spend to tracked script pubkeys.

    +

    Finds all txouts on a transaction that has previously been scanned and indexed.

    +

    Iterates over all outputs with script pubkeys in an index range.

    +

    Returns the txout and script pubkey index of the TxOut at OutPoint.

    +

    Returns None if the TxOut hasn’t been scanned or if nothing matching was found there.

    +

    Returns the script that has been inserted at the index.

    +

    If that index hasn’t been inserted yet it will return None.

    +

    The script pubkeys being tracked by the index.

    +

    Adds a script pubkey to scan for. Returns false and does nothing if spk already exists in the map

    +

    the index will look for outputs spending to whenever it scans new data.

    +

    Iterates over a unused script pubkeys in a index range.

    +

    Here “unused” means that after the script pubkey was stored in the index, the index has +never scanned a transaction output with it.

    +
    Example
    +
    
    +// imagine our spks are indexed like (keychain, derivation_index).
    +let txout_index = SpkTxOutIndex::<(u32, u32)>::default();
    +let all_unused_spks = txout_index.unused_spks(..);
    +let change_index = 1;
    +let unused_change_spks =
    +    txout_index.unused_spks((change_index, u32::MIN)..(change_index, u32::MAX));
    +

    Returns whether the script pubkey at index has been used or not.

    +

    Here “unused” means that after the script pubkey was stored in the index, the index has +never scanned a transaction output with it.

    +

    Marks the script pubkey at index as used even though it hasn’t seen an output with it. +This only has an effect when the index had been added to self already and was unused.

    +

    Returns whether the index was originally present as unused.

    +

    This is useful when you want to reserve a script pubkey for something but don’t want to add +the transaction output using it to the index yet. Other callers will consider index used +until you call unmark_used.

    +

    Undoes the effect of mark_used. Returns whether the index is inserted back into +unused.

    +

    Note that if self has scanned an output with this script pubkey then this will have no +effect.

    +

    Returns the index associated with the script pubkey.

    +

    Computes total input value going from script pubkeys in the index (sent) and total output +value going to script pubkeys in the index (received) in tx. For the sent to be computed +correctly the output being spent must have already been scanned by the index. Calculating +received just uses the transaction outputs directly so will be correct even if it has not +been scanned.

    +

    Computes the net value that this transaction gives to the script pubkeys in the index and +takes from the transaction outputs in the index. Shorthand for calling +sent_and_received and subtracting sent from received.

    +

    Whether any of the inputs of this transaction spend a txout tracked or whether any output +matches one of our script pubkeys.

    +

    It is easily possible to misuse this method and get false negatives by calling it before you +have scanned the TxOuts the transaction is spending. For example if you want to filter out +all the transactions in a block that are irrelevant you must first scan all the +transactions in the block and only then use this method.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/trait.DescriptorExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/trait.DescriptorExt.html new file mode 100644 index 0000000000..3c94b98f54 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/trait.DescriptorExt.html @@ -0,0 +1,5 @@ +DescriptorExt in bdk_chain - Rust

    Trait bdk_chain::DescriptorExt

    source ·
    pub trait DescriptorExt {
    +    fn dust_value(&self) -> u64;
    +}
    Expand description

    A trait to extend the functionality of a miniscript descriptor.

    +

    Required Methods§

    Returns the minimum value (in satoshis) that an output should have to be broadcastable.

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/trait.ForEachTxOut.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/trait.ForEachTxOut.html new file mode 100644 index 0000000000..77f74988e5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/trait.ForEachTxOut.html @@ -0,0 +1,7 @@ +ForEachTxOut in bdk_chain - Rust

    Trait bdk_chain::ForEachTxOut

    source ·
    pub trait ForEachTxOut {
    +    fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut)));
    +}
    Expand description

    Trait to do something with every txout contained in a structure.

    +

    We would prefer just work with things that can give us a Iterator<Item=(OutPoint, &TxOut)> +here but rust’s type system makes it extremely hard to do this (without trait objects).

    +

    Required Methods§

    The provided closure f will called with each outpoint/txout pair.

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_data_traits/trait.ForEachTxOut.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_data_traits/trait.ForEachTxOut.html new file mode 100644 index 0000000000..b7441fb4e7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_data_traits/trait.ForEachTxOut.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_chain/trait.ForEachTxOut.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/index.html new file mode 100644 index 0000000000..bbf8c2d5bf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/index.html @@ -0,0 +1,36 @@ +bdk_chain::tx_graph - Rust

    Module bdk_chain::tx_graph

    source ·
    Expand description

    Module for structures that store and traverse transactions.

    +

    TxGraph is a monotone structure that inserts transactions and indexes spends. The +Additions structure reports changes of TxGraph, but can also be applied on to a +TxGraph as well. Lastly, TxDescendants is an Iterator which traverses descendants of +a given transaction.

    +

    Conflicting transactions are allowed to coexist within a TxGraph. This is useful for +identifying and traversing conflicts and descendants of a given transaction.

    +

    Previewing and applying changes

    +

    Methods that either preview or apply changes to TxGraph will return Additions. +Additions can be applied back on to a TxGraph, or be used to inform persistent storage +of the changes to TxGraph.

    + +
    let mut graph = TxGraph::default();
    +
    +// preview a transaction insertion (not actually inserted)
    +let additions = graph.insert_tx_preview(tx_a);
    +// apply the insertion
    +graph.apply_additions(additions);
    +
    +// you can also insert a transaction directly
    +let already_applied_additions = graph.insert_tx(tx_b);
    +

    A TxGraph can also be updated with another TxGraph.

    + +
    let mut graph = TxGraph::default();
    +let update = TxGraph::new(vec![tx_a, tx_b]);
    +
    +// preview additions as result of the update
    +let additions = graph.determine_additions(&update);
    +// apply the additions
    +graph.apply_additions(additions);
    +
    +// we can also apply the update graph directly
    +// the additions will be empty as we have already applied the same update above
    +let additions = graph.apply_update(update);
    +assert!(additions.is_empty());
    +

    Structs

    A structure that represents changes to a TxGraph.
    An iterator that traverses transaction descendants.
    A graph of transactions and spends.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/sidebar-items.js new file mode 100644 index 0000000000..d4832c6c20 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["Additions","A structure that represents changes to a [`TxGraph`]."],["TxDescendants","An iterator that traverses transaction descendants."],["TxGraph","A graph of transactions and spends."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.Additions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.Additions.html new file mode 100644 index 0000000000..dbee0b1071 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.Additions.html @@ -0,0 +1,18 @@ +Additions in bdk_chain::tx_graph - Rust

    Struct bdk_chain::tx_graph::Additions

    source ·
    pub struct Additions {
    +    pub tx: BTreeSet<Transaction>,
    +    pub txout: BTreeMap<OutPoint, TxOut>,
    +}
    Expand description

    A structure that represents changes to a TxGraph.

    +

    It is named “additions” because TxGraph is monotone so transactions can only be added and +not removed.

    +

    Refer to module-level documentation for more.

    +

    Fields§

    §tx: BTreeSet<Transaction>§txout: BTreeMap<OutPoint, TxOut>

    Implementations§

    Returns true if the Additions is empty (no transactions or txouts).

    +

    Iterates over all outpoints contained within Additions.

    +

    Appends the changes in other into self such that applying self afterwards has the same +effect as sequentially applying the original self and other.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    The provided closure f will called with each outpoint/txout pair.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.TxDescendants.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.TxDescendants.html new file mode 100644 index 0000000000..7110f29ee1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.TxDescendants.html @@ -0,0 +1,42 @@ +TxDescendants in bdk_chain::tx_graph - Rust
    pub struct TxDescendants<'g, F> { /* private fields */ }
    Expand description

    An iterator that traverses transaction descendants.

    +

    This struct is created by the walk_descendants method of TxGraph.

    +

    Trait Implementations§

    The type of the elements being iterated over.
    Advances the iterator and returns the next value. Read more
    🔬This is a nightly-only experimental API. (iter_next_chunk)
    Advances the iterator and returns an array containing the next N values. Read more
    Returns the bounds on the remaining length of the iterator. Read more
    Consumes the iterator, counting the number of iterations and returning it. Read more
    Consumes the iterator, returning the last element. Read more
    🔬This is a nightly-only experimental API. (iter_advance_by)
    Advances the iterator by n elements. Read more
    Returns the nth element of the iterator. Read more
    Creates an iterator starting at the same point, but stepping by +the given amount at each iteration. Read more
    Takes two iterators and creates a new iterator over both in sequence. Read more
    ‘Zips up’ two iterators into a single iterator of pairs. Read more
    🔬This is a nightly-only experimental API. (iter_intersperse)
    Creates a new iterator which places an item generated by separator +between adjacent items of the original iterator. Read more
    Takes a closure and creates an iterator which calls that closure on each +element. Read more
    Calls a closure on each element of an iterator. Read more
    Creates an iterator which uses a closure to determine if an element +should be yielded. Read more
    Creates an iterator that both filters and maps. Read more
    Creates an iterator which gives the current iteration count as well as +the next value. Read more
    Creates an iterator which can use the peek and peek_mut methods +to look at the next element of the iterator without consuming it. See +their documentation for more information. Read more
    Creates an iterator that skips elements based on a predicate. Read more
    Creates an iterator that yields elements based on a predicate. Read more
    Creates an iterator that both yields elements based on a predicate and maps. Read more
    Creates an iterator that skips the first n elements. Read more
    Creates an iterator that yields the first n elements, or fewer +if the underlying iterator ends sooner. Read more
    An iterator adapter similar to fold that holds internal state and +produces a new iterator. Read more
    Creates an iterator that works like map, but flattens nested structure. Read more
    Creates an iterator which ends after the first None. Read more
    Does something with each element of an iterator, passing the value on. Read more
    Borrows an iterator, rather than consuming it. Read more
    Transforms an iterator into a collection. Read more
    🔬This is a nightly-only experimental API. (iter_collect_into)
    Collects all the items from an iterator into a collection. Read more
    Consumes an iterator, creating two collections from it. Read more
    🔬This is a nightly-only experimental API. (iter_is_partitioned)
    Checks if the elements of this iterator are partitioned according to the given predicate, +such that all those that return true precede all those that return false. Read more
    An iterator method that applies a function as long as it returns +successfully, producing a single, final value. Read more
    An iterator method that applies a fallible function to each item in the +iterator, stopping at the first error and returning that error. Read more
    Folds every element into an accumulator by applying an operation, +returning the final result. Read more
    Reduces the elements to a single one, by repeatedly applying a reducing +operation. Read more
    🔬This is a nightly-only experimental API. (iterator_try_reduce)
    Reduces the elements to a single one by repeatedly applying a reducing operation. If the +closure returns a failure, the failure is propagated back to the caller immediately. Read more
    Tests if every element of the iterator matches a predicate. Read more
    Tests if any element of the iterator matches a predicate. Read more
    Searches for an element of an iterator that satisfies a predicate. Read more
    Applies function to the elements of iterator and returns +the first non-none result. Read more
    🔬This is a nightly-only experimental API. (try_find)
    Applies function to the elements of iterator and returns +the first true result or the first error. Read more
    Searches for an element in an iterator, returning its index. Read more
    Returns the element that gives the maximum value from the +specified function. Read more
    Returns the element that gives the maximum value with respect to the +specified comparison function. Read more
    Returns the element that gives the minimum value from the +specified function. Read more
    Returns the element that gives the minimum value with respect to the +specified comparison function. Read more
    Converts an iterator of pairs into a pair of containers. Read more
    Creates an iterator which copies all of its elements. Read more
    Creates an iterator which clones all of its elements. Read more
    🔬This is a nightly-only experimental API. (iter_array_chunks)
    Returns an iterator over N elements of the iterator at a time. Read more
    Sums the elements of an iterator. Read more
    Iterates over the entire iterator, multiplying all the elements Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more
    Lexicographically compares the elements of this Iterator with those +of another. Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more
    Determines if the elements of this Iterator are equal to those of +another. Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Determines if the elements of this Iterator are equal to those of +another with respect to the specified equality function. Read more
    Determines if the elements of this Iterator are unequal to those of +another. Read more
    Determines if the elements of this Iterator are lexicographically +less than those of another. Read more
    Determines if the elements of this Iterator are lexicographically +less or equal to those of another. Read more
    Determines if the elements of this Iterator are lexicographically +greater than those of another. Read more
    Determines if the elements of this Iterator are lexicographically +greater than or equal to those of another. Read more
    🔬This is a nightly-only experimental API. (is_sorted)
    Checks if the elements of this iterator are sorted using the given comparator function. Read more
    🔬This is a nightly-only experimental API. (is_sorted)
    Checks if the elements of this iterator are sorted using the given key extraction +function. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more
    Calculate the sum over the iterator using checked arithmetic. If an over or underflow would +happen it returns None. Read more
    Calculate the sum over the iterator using checked arithmetic. If an over or underflow would +happen it returns None. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type of the elements being iterated over.
    Which kind of iterator are we turning this into?
    Creates an iterator from a value. Read more
    Choose one element at random from the iterator. Read more
    Choose one element at random from the iterator. Read more
    Collects values at random from the iterator into a supplied buffer +until that buffer is filled. Read more
    Collects amount values at random from the iterator into a vector. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.TxGraph.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.TxGraph.html new file mode 100644 index 0000000000..627c5da983 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_chain/tx_graph/struct.TxGraph.html @@ -0,0 +1,70 @@ +TxGraph in bdk_chain::tx_graph - Rust

    Struct bdk_chain::tx_graph::TxGraph

    source ·
    pub struct TxGraph { /* private fields */ }
    Expand description

    A graph of transactions and spends.

    +

    See the module-level documentation for more.

    +

    Implementations§

    Iterate over all tx outputs known by TxGraph.

    +

    Iterate over all full transactions in the graph.

    +

    Get a transaction by txid. This only returns Some for full transactions.

    +

    Refer to get_txout for getting a specific [TxOut].

    +

    Obtains a single tx output (if any) at specified outpoint.

    +

    Returns a BTreeMap of vout to output of the provided txid.

    +

    Calculates the fee of a given transaction. Returns 0 if tx is a coinbase transaction. +Returns Some(_) if we have all the TxOuts being spent by tx in the graph (either as +the full transactions or individual txouts). If the returned value is negative then the +transaction is invalid according to the graph.

    +

    Returns None if we’re missing an input for the tx in the graph.

    +

    Note tx does not have to be in the graph for this to work.

    +

    Contruct a new TxGraph from a list of transaction.

    +

    Inserts the given [TxOut] at [OutPoint].

    +

    Note this will ignore the action if we already have the full transaction that the txout is +alledged to be on (even if it doesn’t match it!).

    +

    Inserts the given transaction into TxGraph.

    +

    The Additions returned will be empty if tx already exists.

    +

    Extends this graph with another so that self becomes the union of the two sets of +transactions.

    +

    The returned Additions is the set difference of update and self (transactions that +exist in update but not in self).

    +

    Applies Additions to TxGraph.

    +

    Previews the resultant Additions when Self is updated against the update graph.

    +

    The Additions would be the set difference of update and self (transactions that +exist in update but not in self).

    +

    Returns the resultant Additions if the given transaction is inserted. Does not actually +mutate Self.

    +

    The Additions result will be empty if tx already existed in self.

    +

    Returns the resultant Additions if the given txout is inserted at outpoint. Does not +mutate self.

    +

    The Additions result will be empty if the outpoint (or a full transaction containing +the outpoint) already existed in self.

    +

    The transactions spending from this output.

    +

    TxGraph allows conflicting transactions within the graph. Obviously the transactions in +the returned will never be in the same blockchain.

    +

    Iterates over the transactions spending from txid.

    +

    The iterator item is a union of (vout, txid-set) where:

    +
      +
    • vout is the provided txid’s outpoint that is being spent
    • +
    • txid-set is the set of txids that is spending the vout
    • +
    +

    Iterate over all partial transactions (outputs only) in the graph.

    +

    Creates an iterator that both filters and maps descendants from the starting txid.

    +

    The supplied closure takes in two inputs (depth, descendant_txid):

    +
      +
    • depth is the distance between the starting txid and the descendant_txid. I.e. if the +descendant is spending an output of the starting txid, the depth will be 1.
    • +
    • descendant_txid is the descendant’s txid which we are considering to walk.
    • +
    +

    The supplied closure returns an Option<T>, allowing the caller to map each node it vists +and decide whether to visit descendants.

    +

    Creates an iterator that both filters and maps conflicting transactions (this includes +descendants of directly-conflicting transactions, which are also considered conflicts).

    +

    Refer to Self::walk_descendants for walk_map usage.

    +

    Given a transaction, return an iterator of txids which directly conflict with the given +transaction’s inputs (spends). The conflicting txids are returned with the given +transaction’s vin (in which it conflicts).

    +

    Note that this only returns directly conflicting txids and does not include descendants of +those txids (which are technically also conflicting).

    +

    Whether the graph has any transactions or outputs in it.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Converts this type into a shared reference of the (usually inferred) input type.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    The provided closure f will called with each outpoint/txout pair.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/all.html new file mode 100644 index 0000000000..d5bb8549ef --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/all.html @@ -0,0 +1 @@ +List of all items in this crate
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/enum.BnbLimit.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/enum.BnbLimit.html new file mode 100644 index 0000000000..c7c7ecc834 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/enum.BnbLimit.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/enum.BnbLimit.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/enum.BranchStrategy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/enum.BranchStrategy.html new file mode 100644 index 0000000000..828b714976 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/enum.BranchStrategy.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/enum.BranchStrategy.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/fn.coin_select_bnb.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/fn.coin_select_bnb.html new file mode 100644 index 0000000000..e48874b207 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/fn.coin_select_bnb.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/fn.coin_select_bnb.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/struct.Bnb.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/struct.Bnb.html new file mode 100644 index 0000000000..ba14dcd65e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/struct.Bnb.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.Bnb.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/struct.BnbIter.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/struct.BnbIter.html new file mode 100644 index 0000000000..6a3347fbe4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/struct.BnbIter.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.BnbIter.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/type.DecideStrategy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/type.DecideStrategy.html new file mode 100644 index 0000000000..8fce4eadc7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/bnb/type.DecideStrategy.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/type.DecideStrategy.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/enum.ExcessStrategyKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/enum.ExcessStrategyKind.html new file mode 100644 index 0000000000..0d0e66ccee --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/enum.ExcessStrategyKind.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/enum.ExcessStrategyKind.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/enum.SelectionConstraint.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/enum.SelectionConstraint.html new file mode 100644 index 0000000000..2307f91807 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/enum.SelectionConstraint.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/enum.SelectionConstraint.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.CoinSelector.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.CoinSelector.html new file mode 100644 index 0000000000..dc2c39ceef --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.CoinSelector.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.CoinSelector.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.CoinSelectorOpt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.CoinSelectorOpt.html new file mode 100644 index 0000000000..46e9c70d52 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.CoinSelectorOpt.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.CoinSelectorOpt.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.ExcessStrategy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.ExcessStrategy.html new file mode 100644 index 0000000000..128686a66a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.ExcessStrategy.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.ExcessStrategy.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.Selection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.Selection.html new file mode 100644 index 0000000000..f5f7d5de7b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.Selection.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.Selection.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.SelectionError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.SelectionError.html new file mode 100644 index 0000000000..ae1ffc0164 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.SelectionError.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.SelectionError.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.WeightedValue.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.WeightedValue.html new file mode 100644 index 0000000000..4446c94b51 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/coin_selector/struct.WeightedValue.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_coin_select/struct.WeightedValue.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/constant.TXIN_BASE_WEIGHT.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/constant.TXIN_BASE_WEIGHT.html new file mode 100644 index 0000000000..b7b808cc25 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/constant.TXIN_BASE_WEIGHT.html @@ -0,0 +1,3 @@ +TXIN_BASE_WEIGHT in bdk_coin_select - Rust
    pub const TXIN_BASE_WEIGHT: u32 = _; // 160u32
    Expand description

    Txin “base” fields include outpoint (32+4) and nSequence (4). This does not include +scriptSigLen or scriptSig.

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.BnbLimit.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.BnbLimit.html new file mode 100644 index 0000000000..896d527319 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.BnbLimit.html @@ -0,0 +1,9 @@ +BnbLimit in bdk_coin_select - Rust
    pub enum BnbLimit {
    +    Rounds(usize),
    +    Duration(Duration),
    +}
    Expand description

    Determines how we should limit rounds of branch and bound.

    +

    Variants§

    §

    Rounds(usize)

    §

    Duration(Duration)

    Trait Implementations§

    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.BranchStrategy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.BranchStrategy.html new file mode 100644 index 0000000000..5350a53e80 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.BranchStrategy.html @@ -0,0 +1,13 @@ +BranchStrategy in bdk_coin_select - Rust
    pub enum BranchStrategy {
    +    Continue,
    +    SkipInclusion,
    +    SkipBoth,
    +}
    Expand description

    Strategy in which we should branch.

    +

    Variants§

    §

    Continue

    We continue exploring subtrees of this node, starting with the inclusion branch.

    +
    §

    SkipInclusion

    We continue exploring ONY the omission branch of this node, skipping the inclusion branch.

    +
    §

    SkipBoth

    We skip both the inclusion and omission branches of this node.

    +

    Implementations§

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.ExcessStrategyKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.ExcessStrategyKind.html new file mode 100644 index 0000000000..d3696a7e02 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.ExcessStrategyKind.html @@ -0,0 +1,13 @@ +ExcessStrategyKind in bdk_coin_select - Rust
    pub enum ExcessStrategyKind {
    +    ToFee,
    +    ToRecipient,
    +    ToDrain,
    +}

    Variants§

    §

    ToFee

    §

    ToRecipient

    §

    ToDrain

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.SelectionConstraint.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.SelectionConstraint.html new file mode 100644 index 0000000000..df271aec34 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/enum.SelectionConstraint.html @@ -0,0 +1,16 @@ +SelectionConstraint in bdk_coin_select - Rust
    pub enum SelectionConstraint {
    +    TargetValue,
    +    TargetFee,
    +    MinAbsoluteFee,
    +    MinDrainValue,
    +}

    Variants§

    §

    TargetValue

    The target is not met

    +
    §

    TargetFee

    The target fee (given the feerate) is not met

    +
    §

    MinAbsoluteFee

    Min absolute fee is not met

    +
    §

    MinDrainValue

    Min drain value is not met

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/fn.coin_select_bnb.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/fn.coin_select_bnb.html new file mode 100644 index 0000000000..96795ab210 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/fn.coin_select_bnb.html @@ -0,0 +1,14 @@ +coin_select_bnb in bdk_coin_select - Rust
    pub fn coin_select_bnb<L>(
        limit: L,
        selector: CoinSelector<'_>
    ) -> Option<CoinSelector<'_>>where
        L: Into<BnbLimit>,
    Expand description

    This is a variation of the Branch and Bound Coin Selection algorithm designed by Murch (as seen +in Bitcoin Core).

    +

    The differences are as follows:

    +
      +
    • In additional to working with effective values, we also work with absolute values. +This way, we can use bounds of absolute values to enforce min_absolute_fee (which is used by +RBF), and max_extra_target (which can be used to increase the possible solution set, given +that the sender is okay with sending extra to the receiver).
    • +
    +

    Murch’s Master Thesis: https://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf +Bitcoin Core Implementation: https://github.com/bitcoin/bitcoin/blob/23.x/src/wallet/coinselection.cpp#L65

    +

    TODO: Another optimization we could do is figure out candidate with smallest waste, and +if we find a result with waste equal to this, we can just break.

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/index.html new file mode 100644 index 0000000000..4bdbe77069 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/index.html @@ -0,0 +1,5 @@ +bdk_coin_select - Rust

    Crate bdk_coin_select

    source ·

    Structs

    Bnb represents the current state of the BnB algorithm.
    CoinSelector is responsible for selecting and deselecting from a set of canididates.
    A WeightedValue represents an input candidate for CoinSelector. This can either be a +single UTXO, or a group of UTXOs that should be spent together.

    Enums

    Determines how we should limit rounds of branch and bound.
    Strategy in which we should branch.

    Constants

    Txin “base” fields include outpoint (32+4) and nSequence (4). This does not include +scriptSigLen or scriptSig.

    Functions

    This is a variation of the Branch and Bound Coin Selection algorithm designed by Murch (as seen +in Bitcoin Core).

    Type Definitions

    Closure to decide the branching strategy, alongside a score (if the current selection is a +candidate solution).
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/sidebar-items.js new file mode 100644 index 0000000000..90be17ea9d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":[["TXIN_BASE_WEIGHT","Txin “base” fields include `outpoint` (32+4) and `nSequence` (4). This does not include `scriptSigLen` or `scriptSig`."]],"enum":[["BnbLimit","Determines how we should limit rounds of branch and bound."],["BranchStrategy","Strategy in which we should branch."],["ExcessStrategyKind",""],["SelectionConstraint",""]],"fn":[["coin_select_bnb","This is a variation of the Branch and Bound Coin Selection algorithm designed by Murch (as seen in Bitcoin Core)."]],"struct":[["Bnb","[`Bnb`] represents the current state of the BnB algorithm."],["BnbIter",""],["CoinSelector","[`CoinSelector`] is responsible for selecting and deselecting from a set of canididates."],["CoinSelectorOpt",""],["ExcessStrategy",""],["Selection",""],["SelectionError",""],["WeightedValue","A [`WeightedValue`] represents an input candidate for [`CoinSelector`]. This can either be a single UTXO, or a group of UTXOs that should be spent together."]],"type":[["DecideStrategy","Closure to decide the branching strategy, alongside a score (if the current selection is a candidate solution)."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.Bnb.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.Bnb.html new file mode 100644 index 0000000000..4eb7615f60 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.Bnb.html @@ -0,0 +1,22 @@ +Bnb in bdk_coin_select - Rust

    Struct bdk_coin_select::Bnb

    source ·
    pub struct Bnb<'c, S> {
    +    pub pool: Vec<(usize, &'c WeightedValue)>,
    +    pub pool_pos: usize,
    +    pub best_score: S,
    +    pub selection: CoinSelector<'c>,
    +    pub rem_abs: u64,
    +    pub rem_eff: i64,
    +}
    Expand description

    Bnb represents the current state of the BnB algorithm.

    +

    Fields§

    §pool: Vec<(usize, &'c WeightedValue)>§pool_pos: usize§best_score: S§selection: CoinSelector<'c>§rem_abs: u64§rem_eff: i64

    Implementations§

    Creates a new Bnb.

    +

    Turns our Bnb state into an iterator.

    +

    strategy should assess our current selection/node and determine the branching strategy and +whether this selection is a candidate solution (if so, return the score of the selection).

    +

    Attempt to backtrack to the previously selected node’s omission branch, return false +otherwise (no more solutions).

    +

    Continue down this branch, skip inclusion branch if specified.

    +

    Compare advertised score with current best. New best will be the smaller value. Return true +if best is replaced.

    +

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.BnbIter.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.BnbIter.html new file mode 100644 index 0000000000..60aa3553df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.BnbIter.html @@ -0,0 +1,38 @@ +BnbIter in bdk_coin_select - Rust

    Struct bdk_coin_select::BnbIter

    source ·
    pub struct BnbIter<'c, 'f, S> { /* private fields */ }

    Trait Implementations§

    The type of the elements being iterated over.
    Advances the iterator and returns the next value. Read more
    🔬This is a nightly-only experimental API. (iter_next_chunk)
    Advances the iterator and returns an array containing the next N values. Read more
    Returns the bounds on the remaining length of the iterator. Read more
    Consumes the iterator, counting the number of iterations and returning it. Read more
    Consumes the iterator, returning the last element. Read more
    🔬This is a nightly-only experimental API. (iter_advance_by)
    Advances the iterator by n elements. Read more
    Returns the nth element of the iterator. Read more
    Creates an iterator starting at the same point, but stepping by +the given amount at each iteration. Read more
    Takes two iterators and creates a new iterator over both in sequence. Read more
    ‘Zips up’ two iterators into a single iterator of pairs. Read more
    🔬This is a nightly-only experimental API. (iter_intersperse)
    Creates a new iterator which places an item generated by separator +between adjacent items of the original iterator. Read more
    Takes a closure and creates an iterator which calls that closure on each +element. Read more
    Calls a closure on each element of an iterator. Read more
    Creates an iterator which uses a closure to determine if an element +should be yielded. Read more
    Creates an iterator that both filters and maps. Read more
    Creates an iterator which gives the current iteration count as well as +the next value. Read more
    Creates an iterator which can use the peek and peek_mut methods +to look at the next element of the iterator without consuming it. See +their documentation for more information. Read more
    Creates an iterator that skips elements based on a predicate. Read more
    Creates an iterator that yields elements based on a predicate. Read more
    Creates an iterator that both yields elements based on a predicate and maps. Read more
    Creates an iterator that skips the first n elements. Read more
    Creates an iterator that yields the first n elements, or fewer +if the underlying iterator ends sooner. Read more
    An iterator adapter similar to fold that holds internal state and +produces a new iterator. Read more
    Creates an iterator that works like map, but flattens nested structure. Read more
    Creates an iterator which ends after the first None. Read more
    Does something with each element of an iterator, passing the value on. Read more
    Borrows an iterator, rather than consuming it. Read more
    Transforms an iterator into a collection. Read more
    🔬This is a nightly-only experimental API. (iter_collect_into)
    Collects all the items from an iterator into a collection. Read more
    Consumes an iterator, creating two collections from it. Read more
    🔬This is a nightly-only experimental API. (iter_is_partitioned)
    Checks if the elements of this iterator are partitioned according to the given predicate, +such that all those that return true precede all those that return false. Read more
    An iterator method that applies a function as long as it returns +successfully, producing a single, final value. Read more
    An iterator method that applies a fallible function to each item in the +iterator, stopping at the first error and returning that error. Read more
    Folds every element into an accumulator by applying an operation, +returning the final result. Read more
    Reduces the elements to a single one, by repeatedly applying a reducing +operation. Read more
    🔬This is a nightly-only experimental API. (iterator_try_reduce)
    Reduces the elements to a single one by repeatedly applying a reducing operation. If the +closure returns a failure, the failure is propagated back to the caller immediately. Read more
    Tests if every element of the iterator matches a predicate. Read more
    Tests if any element of the iterator matches a predicate. Read more
    Searches for an element of an iterator that satisfies a predicate. Read more
    Applies function to the elements of iterator and returns +the first non-none result. Read more
    🔬This is a nightly-only experimental API. (try_find)
    Applies function to the elements of iterator and returns +the first true result or the first error. Read more
    Searches for an element in an iterator, returning its index. Read more
    Returns the element that gives the maximum value from the +specified function. Read more
    Returns the element that gives the maximum value with respect to the +specified comparison function. Read more
    Returns the element that gives the minimum value from the +specified function. Read more
    Returns the element that gives the minimum value with respect to the +specified comparison function. Read more
    Converts an iterator of pairs into a pair of containers. Read more
    Creates an iterator which copies all of its elements. Read more
    Creates an iterator which clones all of its elements. Read more
    🔬This is a nightly-only experimental API. (iter_array_chunks)
    Returns an iterator over N elements of the iterator at a time. Read more
    Sums the elements of an iterator. Read more
    Iterates over the entire iterator, multiplying all the elements Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more
    Lexicographically compares the elements of this Iterator with those +of another. Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more
    Determines if the elements of this Iterator are equal to those of +another. Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Determines if the elements of this Iterator are equal to those of +another with respect to the specified equality function. Read more
    Determines if the elements of this Iterator are unequal to those of +another. Read more
    Determines if the elements of this Iterator are lexicographically +less than those of another. Read more
    Determines if the elements of this Iterator are lexicographically +less or equal to those of another. Read more
    Determines if the elements of this Iterator are lexicographically +greater than those of another. Read more
    Determines if the elements of this Iterator are lexicographically +greater than or equal to those of another. Read more
    🔬This is a nightly-only experimental API. (is_sorted)
    Checks if the elements of this iterator are sorted using the given comparator function. Read more
    🔬This is a nightly-only experimental API. (is_sorted)
    Checks if the elements of this iterator are sorted using the given key extraction +function. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type of the elements being iterated over.
    Which kind of iterator are we turning this into?
    Creates an iterator from a value. Read more
    Choose one element at random from the iterator. Read more
    Choose one element at random from the iterator. Read more
    Collects values at random from the iterator into a supplied buffer +until that buffer is filled. Read more
    Collects amount values at random from the iterator into a vector. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.CoinSelector.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.CoinSelector.html new file mode 100644 index 0000000000..88b82e56eb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.CoinSelector.html @@ -0,0 +1,17 @@ +CoinSelector in bdk_coin_select - Rust
    pub struct CoinSelector<'a> {
    +    pub opts: &'a CoinSelectorOpt,
    +    pub candidates: &'a Vec<WeightedValue>,
    +    /* private fields */
    +}
    Expand description

    CoinSelector is responsible for selecting and deselecting from a set of canididates.

    +

    Fields§

    §opts: &'a CoinSelectorOpt§candidates: &'a Vec<WeightedValue>

    Implementations§

    Weight sum of all selected inputs.

    +

    Effective value sum of all selected inputs.

    +

    Absolute value sum of all selected inputs.

    +

    Waste sum of all selected inputs.

    +

    Current weight of template tx + selected inputs.

    +

    Current excess.

    +

    This is the effective target value.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.CoinSelectorOpt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.CoinSelectorOpt.html new file mode 100644 index 0000000000..0b0e5ce213 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.CoinSelectorOpt.html @@ -0,0 +1,26 @@ +CoinSelectorOpt in bdk_coin_select - Rust
    pub struct CoinSelectorOpt {
    +    pub target_value: Option<u64>,
    +    pub max_extra_target: u64,
    +    pub target_feerate: f32,
    +    pub long_term_feerate: Option<f32>,
    +    pub min_absolute_fee: u64,
    +    pub base_weight: u32,
    +    pub drain_weight: u32,
    +    pub spend_drain_weight: u32,
    +    pub min_drain_value: u64,
    +}

    Fields§

    §target_value: Option<u64>

    The value we need to select. +If the value is None then the selection will be complete if it can pay for the drain +output and satisfy the other constraints (e.g. minimum fees).

    +
    §max_extra_target: u64

    Additional leeway for the target value.

    +
    §target_feerate: f32

    The feerate we should try and achieve in sats per weight unit.

    +
    §long_term_feerate: Option<f32>

    The feerate

    +
    §min_absolute_fee: u64

    The minimum absolute fee. I.e. needed for RBF.

    +
    §base_weight: u32

    The weight of the template transaction including fixed fields and outputs.

    +
    §drain_weight: u32

    Additional weight if we include the drain (change) output.

    +
    §spend_drain_weight: u32

    Weight of spending the drain (change) output in the future.

    +
    §min_drain_value: u64

    Minimum value allowed for a drain (change) output.

    +

    Implementations§

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.ExcessStrategy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.ExcessStrategy.html new file mode 100644 index 0000000000..605d365a86 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.ExcessStrategy.html @@ -0,0 +1,12 @@ +ExcessStrategy in bdk_coin_select - Rust
    pub struct ExcessStrategy {
    +    pub recipient_value: Option<u64>,
    +    pub drain_value: Option<u64>,
    +    pub fee: u64,
    +    pub weight: u32,
    +    pub waste: i64,
    +}

    Fields§

    §recipient_value: Option<u64>§drain_value: Option<u64>§fee: u64§weight: u32§waste: i64

    Implementations§

    Returns feerate in sats/wu.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.Selection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.Selection.html new file mode 100644 index 0000000000..5e62511f4e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.Selection.html @@ -0,0 +1,10 @@ +Selection in bdk_coin_select - Rust

    Struct bdk_coin_select::Selection

    source ·
    pub struct Selection {
    +    pub selected: BTreeSet<usize>,
    +    pub excess: u64,
    +    pub excess_strategies: HashMap<ExcessStrategyKind, ExcessStrategy>,
    +}

    Fields§

    §selected: BTreeSet<usize>§excess: u64§excess_strategies: HashMap<ExcessStrategyKind, ExcessStrategy>

    Implementations§

    Returns the ExcessStrategy that results in the least waste.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.SelectionError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.SelectionError.html new file mode 100644 index 0000000000..3af72569ea --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.SelectionError.html @@ -0,0 +1,6 @@ +SelectionError in bdk_coin_select - Rust
    pub struct SelectionError { /* private fields */ }

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.WeightedValue.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.WeightedValue.html new file mode 100644 index 0000000000..e5dbdabe19 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/struct.WeightedValue.html @@ -0,0 +1,21 @@ +WeightedValue in bdk_coin_select - Rust
    pub struct WeightedValue {
    +    pub value: u64,
    +    pub weight: u32,
    +    pub input_count: usize,
    +    pub is_segwit: bool,
    +}
    Expand description

    A WeightedValue represents an input candidate for CoinSelector. This can either be a +single UTXO, or a group of UTXOs that should be spent together.

    +

    Fields§

    §value: u64

    Total value of the UTXO(s) that this WeightedValue represents.

    +
    §weight: u32

    Total weight of including this/these UTXO(s). +txin fields: prevout, nSequence, scriptSigLen, scriptSig, scriptWitnessLen, +scriptWitness should all be included.

    +
    §input_count: usize

    Total number of inputs; so we can calculate extra varint weight due to vin len changes.

    +
    §is_segwit: bool

    Whether this WeightedValue contains at least one segwit spend.

    +

    Implementations§

    Create a new WeightedValue that represents a single input.

    +

    satisfaction_weight is the weight of scriptSigLen + scriptSig + scriptWitnessLen + scriptWitness.

    +

    Effective value of this input candidate: actual_value - input_weight * feerate (sats/wu).

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/type.DecideStrategy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/type.DecideStrategy.html new file mode 100644 index 0000000000..a22fb9a8a2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_coin_select/type.DecideStrategy.html @@ -0,0 +1,3 @@ +DecideStrategy in bdk_coin_select - Rust

    Type Definition bdk_coin_select::DecideStrategy

    source ·
    pub type DecideStrategy<'c, S> = dyn Fn(&Bnb<'c, S>) -> (BranchStrategy, Option<S>);
    Expand description

    Closure to decide the branching strategy, alongside a score (if the current selection is a +candidate solution).

    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/all.html new file mode 100644 index 0000000000..84c4cc6eef --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Structs

    Traits

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/index.html new file mode 100644 index 0000000000..e4b4d21d59 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/index.html @@ -0,0 +1,18 @@ +bdk_electrum - Rust

    Crate bdk_electrum

    source ·
    Expand description

    This crate is used for updating structures of the [bdk_chain] crate with data from electrum.

    +

    The star of the show is the ElectrumExt::scan method, which scans for relevant blockchain +data (via electrum) and outputs an ElectrumUpdate.

    +

    An ElectrumUpdate only includes txids and no full transactions. The caller is responsible +for obtaining full transactions before applying. This can be done with +these steps:

    +
      +
    1. +

      Determine which full transactions are missing. The method missing_full_txs of +ElectrumUpdate can be used.

      +
    2. +
    3. +

      Obtaining the full transactions. To do this via electrum, the method +batch_transaction_get can be used.

      +
    4. +
    +

    Refer to bdk_electrum_example for a complete example.

    +

    Re-exports

    pub use bdk_chain;
    pub use electrum_client;

    Structs

    Traits

    Trait to extend [electrum_client::Client] functionality.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/sidebar-items.js new file mode 100644 index 0000000000..f427138cd5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["ElectrumUpdate","The result of [`ElectrumExt::scan`]."]],"trait":[["ElectrumExt","Trait to extend [`electrum_client::Client`] functionality."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumUpdate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumUpdate.html new file mode 100644 index 0000000000..e28ba04e41 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumUpdate.html @@ -0,0 +1,16 @@ +ElectrumUpdate in bdk_electrum - Rust
    pub struct ElectrumUpdate<K, P> {
    +    pub chain_update: SparseChain<P>,
    +    pub last_active_indices: BTreeMap<K, u32>,
    +}
    Expand description

    The result of ElectrumExt::scan.

    +

    Fields§

    §chain_update: SparseChain<P>

    The internal [SparseChain] update.

    +
    §last_active_indices: BTreeMap<K, u32>

    The last keychain script pubkey indices which had transaction histories.

    +

    Implementations§

    Return a list of missing full transactions that are required to inflate_update.

    +

    Transform the ElectrumUpdate into a [KeychainScan] which can be applied to a +tracker.

    +

    This will fail if there are missing full transactions not provided via new_txs.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/trait.ElectrumExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/trait.ElectrumExt.html new file mode 100644 index 0000000000..d390b5d827 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/trait.ElectrumExt.html @@ -0,0 +1,20 @@ +ElectrumExt in bdk_electrum - Rust
    pub trait ElectrumExt {
    +    fn get_tip(&self) -> Result<(u32, BlockHash), Error>;
    +    fn scan<K: Ord + Clone>(
            &self,
            local_chain: &BTreeMap<u32, BlockHash>,
            keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, Script)>>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            stop_gap: usize,
            batch_size: usize
        ) -> Result<ElectrumUpdate<K, TxHeight>, Error>; + + fn scan_without_keychain(
            &self,
            local_chain: &BTreeMap<u32, BlockHash>,
            misc_spks: impl IntoIterator<Item = Script>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            batch_size: usize
        ) -> Result<SparseChain, Error> { ... } +}
    Expand description

    Trait to extend [electrum_client::Client] functionality.

    +

    Refer to crate-level documentation for more.

    +

    Required Methods§

    Fetch the latest block height.

    +

    Scan the blockchain (via electrum) for the data specified. This returns a ElectrumUpdate +which can be transformed into a [KeychainScan] after we find all the missing full +transactions.

    +
      +
    • local_chain: the most recent block hashes present locally
    • +
    • keychain_spks: keychains that we want to scan transactions for
    • +
    • txids: transactions that we want updated [ChainPosition]s for
    • +
    • outpoints: transactions associated with these outpoints (residing, spending) that we +want to included in the update
    • +
    +

    Provided Methods§

    Convenience method to call scan without requiring a keychain.

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/all.html new file mode 100644 index 0000000000..06790e61de --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Traits

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/async_ext/trait.EsploraAsyncExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/async_ext/trait.EsploraAsyncExt.html new file mode 100644 index 0000000000..4c6d452233 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/async_ext/trait.EsploraAsyncExt.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_esplora/trait.EsploraAsyncExt.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/blocking_ext/trait.EsploraExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/blocking_ext/trait.EsploraExt.html new file mode 100644 index 0000000000..137b7f45e5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/blocking_ext/trait.EsploraExt.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_esplora/trait.EsploraExt.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/index.html new file mode 100644 index 0000000000..ccfd3c57d8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/index.html @@ -0,0 +1,22 @@ +bdk_esplora - Rust

    Crate bdk_esplora

    source ·
    Expand description

    BDK Esplora

    +

    BDK Esplora extends esplora_client to update [bdk_chain] structures +from an Esplora server.

    +

    Usage

    +

    There are two versions of the extension trait (blocking and async).

    +

    For blocking-only:

    +
    bdk_esplora = { version = "0.1", features = ["blocking"] }
    +
    +

    For async-only:

    +
    bdk_esplora = { version = "0.1", features = ["async"] }
    +
    +

    For async-only (with https):

    +
    bdk_esplora = { version = "0.1", features = ["async-https"] }
    +
    +

    To use the extension trait:

    + +
    // for blocking
    +use bdk_esplora::EsploraExt;
    +// for async
    +use bdk_esplora::EsploraAsyncExt;
    + +

    Re-exports

    pub use esplora_client;

    Traits

    Trait to extend [esplora_client::BlockingClient] functionality.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/sidebar-items.js new file mode 100644 index 0000000000..b522e9403d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["EsploraAsyncExt",""],["EsploraExt","Trait to extend [`esplora_client::BlockingClient`] functionality."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraAsyncExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraAsyncExt.html new file mode 100644 index 0000000000..98a87bcaee --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraAsyncExt.html @@ -0,0 +1,18 @@ +EsploraAsyncExt in bdk_esplora - Rust
    pub trait EsploraAsyncExt {
    +    fn scan<'life0, 'life1, 'async_trait, K>(
            &'life0 self,
            local_chain: &'life1 BTreeMap<u32, BlockHash>,
            keychain_spks: BTreeMap<K, impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = (u32, Script)> + Send> + Send>,
            txids: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = Txid> + Send> + Send,
            outpoints: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = OutPoint> + Send> + Send,
            stop_gap: usize,
            parallel_requests: usize
        ) -> Pin<Box<dyn Future<Output = Result<KeychainScan<K, ConfirmationTime>, Error>> + Send + 'async_trait>>
        where
            K: 'async_trait + Ord + Clone + Send,
            Self: 'async_trait,
            'life0: 'async_trait,
            'life1: 'async_trait
    ; + + fn scan_without_keychain<'life0, 'life1, 'async_trait>(
            &'life0 self,
            local_chain: &'life1 BTreeMap<u32, BlockHash>,
            misc_spks: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = Script> + Send> + Send,
            txids: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = Txid> + Send> + Send,
            outpoints: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = OutPoint> + Send> + Send,
            parallel_requests: usize
        ) -> Pin<Box<dyn Future<Output = Result<ChainGraph<ConfirmationTime>, Error>> + Send + 'async_trait>>
        where
            Self: Sync + 'async_trait,
            'life0: 'async_trait,
            'life1: 'async_trait
    , + { ... } +}

    Required Methods§

    Scan the blockchain (via esplora) for the data specified and returns a [KeychainScan].

    +
      +
    • local_chain: the most recent block hashes present locally
    • +
    • keychain_spks: keychains that we want to scan transactions for
    • +
    • txids: transactions that we want updated ChainPositions for
    • +
    • outpoints: transactions associated with these outpoints (residing, spending) that we +want to included in the update
    • +
    +

    The scan for each keychain stops after a gap of stop_gap script pubkeys with no associated +transactions. parallel_requests specifies the max number of HTTP requests to make in +parallel.

    +

    Provided Methods§

    Convenience method to call scan without requiring a keychain.

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html new file mode 100644 index 0000000000..a9dc3f9358 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html @@ -0,0 +1,19 @@ +EsploraExt in bdk_esplora - Rust

    Trait bdk_esplora::EsploraExt

    source ·
    pub trait EsploraExt {
    +    fn scan<K: Ord + Clone>(
            &self,
            local_chain: &BTreeMap<u32, BlockHash>,
            keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, Script)>>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            stop_gap: usize,
            parallel_requests: usize
        ) -> Result<KeychainScan<K, ConfirmationTime>, Error>; + + fn scan_without_keychain(
            &self,
            local_chain: &BTreeMap<u32, BlockHash>,
            misc_spks: impl IntoIterator<Item = Script>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            parallel_requests: usize
        ) -> Result<ChainGraph<ConfirmationTime>, Error> { ... } +}
    Expand description

    Trait to extend [esplora_client::BlockingClient] functionality.

    +

    Refer to crate-level documentation for more.

    +

    Required Methods§

    Scan the blockchain (via esplora) for the data specified and returns a [KeychainScan].

    +
      +
    • local_chain: the most recent block hashes present locally
    • +
    • keychain_spks: keychains that we want to scan transactions for
    • +
    • txids: transactions that we want updated ChainPositions for
    • +
    • outpoints: transactions associated with these outpoints (residing, spending) that we +want to included in the update
    • +
    +

    The scan for each keychain stops after a gap of stop_gap script pubkeys with no associated +transactions. parallel_requests specifies the max number of HTTP requests to make in +parallel.

    +

    Provided Methods§

    Convenience method to call scan without requiring a keychain.

    +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/all.html new file mode 100644 index 0000000000..1200a31259 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Functions

    Constants

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.PARALLEL_REQUESTS.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.PARALLEL_REQUESTS.html new file mode 100644 index 0000000000..267c8c978e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.PARALLEL_REQUESTS.html @@ -0,0 +1 @@ +PARALLEL_REQUESTS in bdk_esplora_wallet_example - Rust
    pub(crate) const PARALLEL_REQUESTS: usize = 5;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.SEND_AMOUNT.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.SEND_AMOUNT.html new file mode 100644 index 0000000000..48f2ae8abf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.SEND_AMOUNT.html @@ -0,0 +1 @@ +SEND_AMOUNT in bdk_esplora_wallet_example - Rust
    pub(crate) const SEND_AMOUNT: u64 = 5000;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.STOP_GAP.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.STOP_GAP.html new file mode 100644 index 0000000000..5d1c0cd5f8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/constant.STOP_GAP.html @@ -0,0 +1 @@ +STOP_GAP in bdk_esplora_wallet_example - Rust
    pub(crate) const STOP_GAP: usize = 50;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/fn.main.html new file mode 100644 index 0000000000..190b42c146 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/fn.main.html @@ -0,0 +1 @@ +main in bdk_esplora_wallet_example - Rust
    pub(crate) fn main() -> Result<(), Box<dyn Error>>
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/index.html new file mode 100644 index 0000000000..5021d2f5e1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/index.html @@ -0,0 +1 @@ +bdk_esplora_wallet_example - Rust

    Constants

    SEND_AMOUNT ðŸ”’
    STOP_GAP ðŸ”’

    Functions

    main ðŸ”’
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/sidebar-items.js new file mode 100644 index 0000000000..a6121128e9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora_wallet_example/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":[["PARALLEL_REQUESTS",""],["SEND_AMOUNT",""],["STOP_GAP",""]],"fn":[["main",""]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/all.html new file mode 100644 index 0000000000..fb37fb9e5f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Structs

    Enums

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/enum.FileError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/enum.FileError.html new file mode 100644 index 0000000000..6cb0a391ed --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/enum.FileError.html @@ -0,0 +1,12 @@ +FileError in bdk_file_store - Rust
    pub enum FileError {
    +    Io(Error),
    +    InvalidMagicBytes([u8; 12]),
    +}
    Expand description

    Error that occurs due to problems encountered with the file.

    +

    Variants§

    §

    Io(Error)

    IO error, this may mean that the file is too short.

    +
    §

    InvalidMagicBytes([u8; 12])

    Magic bytes do not match expected.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/enum.IterError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/enum.IterError.html new file mode 100644 index 0000000000..92de990200 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/enum.IterError.html @@ -0,0 +1,12 @@ +IterError in bdk_file_store - Rust
    pub enum IterError {
    +    Io(Error),
    +    Bincode(ErrorKind),
    +}
    Expand description

    Error type for EntryIter.

    +

    Variants§

    §

    Io(Error)

    Failure to read from file.

    +
    §

    Bincode(ErrorKind)

    Failure to decode data from file.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/enum.FileError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/enum.FileError.html new file mode 100644 index 0000000000..0df3f11027 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/enum.FileError.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_file_store/enum.FileError.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/enum.IterError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/enum.IterError.html new file mode 100644 index 0000000000..51696a51d7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/enum.IterError.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_file_store/enum.IterError.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/struct.EntryIter.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/struct.EntryIter.html new file mode 100644 index 0000000000..92fbcf283b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/struct.EntryIter.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_file_store/struct.EntryIter.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/struct.KeychainStore.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/struct.KeychainStore.html new file mode 100644 index 0000000000..6ca1dc38b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/file_store/struct.KeychainStore.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_file_store/struct.KeychainStore.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/index.html new file mode 100644 index 0000000000..470222b8b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/index.html @@ -0,0 +1,7 @@ +bdk_file_store - Rust

    Crate bdk_file_store

    source ·
    Expand description

    BDK File Store

    +

    This is a simple append-only flat file implementation of +Persist.

    +

    The main structure is KeychainStore, which can be used with bdk’s +Wallet to persist wallet data into a flat file.

    +

    Structs

    Iterator over entries in a file store.
    Persists an append only list of KeychainChangeSet<K,P> to a single file. +[KeychainChangeSet<K,P>] record the changes made to a [KeychainTracker<K,P>].

    Enums

    Error that occurs due to problems encountered with the file.
    Error type for EntryIter.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/sidebar-items.js new file mode 100644 index 0000000000..1ab40e4925 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["FileError","Error that occurs due to problems encountered with the file."],["IterError","Error type for [`EntryIter`]."]],"struct":[["EntryIter","Iterator over entries in a file store."],["KeychainStore","Persists an append only list of `KeychainChangeSet` to a single file. [`KeychainChangeSet`] record the changes made to a [`KeychainTracker`]."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.EntryIter.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.EntryIter.html new file mode 100644 index 0000000000..67fb7a2811 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.EntryIter.html @@ -0,0 +1,41 @@ +EntryIter in bdk_file_store - Rust

    Struct bdk_file_store::EntryIter

    source ·
    pub struct EntryIter<'a, V> { /* private fields */ }
    Expand description

    Iterator over entries in a file store.

    +

    Reads and returns an entry each time next is called. If an error occurs while reading the +iterator will yield a Result::Err(_) instead and then None for the next call to next.

    +

    Implementations§

    Trait Implementations§

    The type of the elements being iterated over.
    Advances the iterator and returns the next value. Read more
    🔬This is a nightly-only experimental API. (iter_next_chunk)
    Advances the iterator and returns an array containing the next N values. Read more
    Returns the bounds on the remaining length of the iterator. Read more
    Consumes the iterator, counting the number of iterations and returning it. Read more
    Consumes the iterator, returning the last element. Read more
    🔬This is a nightly-only experimental API. (iter_advance_by)
    Advances the iterator by n elements. Read more
    Returns the nth element of the iterator. Read more
    Creates an iterator starting at the same point, but stepping by +the given amount at each iteration. Read more
    Takes two iterators and creates a new iterator over both in sequence. Read more
    ‘Zips up’ two iterators into a single iterator of pairs. Read more
    🔬This is a nightly-only experimental API. (iter_intersperse)
    Creates a new iterator which places an item generated by separator +between adjacent items of the original iterator. Read more
    Takes a closure and creates an iterator which calls that closure on each +element. Read more
    Calls a closure on each element of an iterator. Read more
    Creates an iterator which uses a closure to determine if an element +should be yielded. Read more
    Creates an iterator that both filters and maps. Read more
    Creates an iterator which gives the current iteration count as well as +the next value. Read more
    Creates an iterator which can use the peek and peek_mut methods +to look at the next element of the iterator without consuming it. See +their documentation for more information. Read more
    Creates an iterator that skips elements based on a predicate. Read more
    Creates an iterator that yields elements based on a predicate. Read more
    Creates an iterator that both yields elements based on a predicate and maps. Read more
    Creates an iterator that skips the first n elements. Read more
    Creates an iterator that yields the first n elements, or fewer +if the underlying iterator ends sooner. Read more
    An iterator adapter similar to fold that holds internal state and +produces a new iterator. Read more
    Creates an iterator that works like map, but flattens nested structure. Read more
    Creates an iterator which ends after the first None. Read more
    Does something with each element of an iterator, passing the value on. Read more
    Borrows an iterator, rather than consuming it. Read more
    Transforms an iterator into a collection. Read more
    🔬This is a nightly-only experimental API. (iter_collect_into)
    Collects all the items from an iterator into a collection. Read more
    Consumes an iterator, creating two collections from it. Read more
    🔬This is a nightly-only experimental API. (iter_is_partitioned)
    Checks if the elements of this iterator are partitioned according to the given predicate, +such that all those that return true precede all those that return false. Read more
    An iterator method that applies a function as long as it returns +successfully, producing a single, final value. Read more
    An iterator method that applies a fallible function to each item in the +iterator, stopping at the first error and returning that error. Read more
    Folds every element into an accumulator by applying an operation, +returning the final result. Read more
    Reduces the elements to a single one, by repeatedly applying a reducing +operation. Read more
    🔬This is a nightly-only experimental API. (iterator_try_reduce)
    Reduces the elements to a single one by repeatedly applying a reducing operation. If the +closure returns a failure, the failure is propagated back to the caller immediately. Read more
    Tests if every element of the iterator matches a predicate. Read more
    Tests if any element of the iterator matches a predicate. Read more
    Searches for an element of an iterator that satisfies a predicate. Read more
    Applies function to the elements of iterator and returns +the first non-none result. Read more
    🔬This is a nightly-only experimental API. (try_find)
    Applies function to the elements of iterator and returns +the first true result or the first error. Read more
    Searches for an element in an iterator, returning its index. Read more
    Returns the element that gives the maximum value from the +specified function. Read more
    Returns the element that gives the maximum value with respect to the +specified comparison function. Read more
    Returns the element that gives the minimum value from the +specified function. Read more
    Returns the element that gives the minimum value with respect to the +specified comparison function. Read more
    Converts an iterator of pairs into a pair of containers. Read more
    Creates an iterator which copies all of its elements. Read more
    Creates an iterator which clones all of its elements. Read more
    🔬This is a nightly-only experimental API. (iter_array_chunks)
    Returns an iterator over N elements of the iterator at a time. Read more
    Sums the elements of an iterator. Read more
    Iterates over the entire iterator, multiplying all the elements Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more
    Lexicographically compares the elements of this Iterator with those +of another. Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Lexicographically compares the elements of this Iterator with those +of another with respect to the specified comparison function. Read more
    Determines if the elements of this Iterator are equal to those of +another. Read more
    🔬This is a nightly-only experimental API. (iter_order_by)
    Determines if the elements of this Iterator are equal to those of +another with respect to the specified equality function. Read more
    Determines if the elements of this Iterator are unequal to those of +another. Read more
    Determines if the elements of this Iterator are lexicographically +less than those of another. Read more
    Determines if the elements of this Iterator are lexicographically +less or equal to those of another. Read more
    Determines if the elements of this Iterator are lexicographically +greater than those of another. Read more
    Determines if the elements of this Iterator are lexicographically +greater than or equal to those of another. Read more
    🔬This is a nightly-only experimental API. (is_sorted)
    Checks if the elements of this iterator are sorted using the given comparator function. Read more
    🔬This is a nightly-only experimental API. (is_sorted)
    Checks if the elements of this iterator are sorted using the given key extraction +function. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type of the elements being iterated over.
    Which kind of iterator are we turning this into?
    Creates an iterator from a value. Read more
    Choose one element at random from the iterator. Read more
    Choose one element at random from the iterator. Read more
    Collects values at random from the iterator into a supplied buffer +until that buffer is filled. Read more
    Collects amount values at random from the iterator into a vector. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.KeychainStore.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.KeychainStore.html new file mode 100644 index 0000000000..2c00e568e4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.KeychainStore.html @@ -0,0 +1,33 @@ +KeychainStore in bdk_file_store - Rust
    pub struct KeychainStore<K, P> { /* private fields */ }
    Expand description

    Persists an append only list of KeychainChangeSet<K,P> to a single file. +[KeychainChangeSet<K,P>] record the changes made to a [KeychainTracker<K,P>].

    +

    Implementations§

    Creates a new store from a File.

    +

    The file must have been opened with read, write permissions.

    +

    Creates or loads a a store from db_path. If no file exists there it will be created.

    +

    Iterates over the stored changeset from first to last changing the seek position at each +iteration.

    +

    The iterator may fail to read an entry and therefore return an error. However the first time +it returns an error will be the last. After doing so the iterator will always yield None.

    +

    WARNING: This method changes the write position in the underlying file. You should +always iterate over all entries until None is returned if you want your next write to go +at the end, otherwise you will write over existing enties.

    +

    Loads all the changesets that have been stored as one giant changeset.

    +

    This function returns a tuple of the aggregate changeset and a result which indicates +whether an error occurred while reading or deserializing one of the entries. If so the +changeset will consist of all of those it was able to read.

    +

    You should usually check the error. In many applications it may make sense to do a full +wallet scan with a stop gap after getting an error since it is likely that one of the +changesets it was unable to read changed the derivation indicies of the tracker.

    +

    WARNING: This method changes the write position of the underlying file. The next +changeset will be written over the erroring entry (or the end of the file if none existed).

    +

    Reads and applies all the changesets stored sequentially to tracker, stopping when it fails +to read the next one.

    +

    WARNING: This method changes the write position of the underlying file. The next +changeset will be written over the erroring entry (or the end of the file if none existed).

    +

    Append a new changeset to the file and truncate file to the end of the appended changeset.

    +

    The truncation is to avoid the possibility of having a valid, but inconsistent changeset +directly after the appended changeset.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    The error the backend returns when it fails to write.
    The error the backend returns when it fails to load.
    Appends a new changeset to the persistance backend. Read more
    Applies all the changesets the backend has received to tracker.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/all.html new file mode 100644 index 0000000000..e9afdc85cc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/all.html @@ -0,0 +1 @@ +List of all items in this crate
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.PlanState.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.PlanState.html new file mode 100644 index 0000000000..e77588f804 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.PlanState.html @@ -0,0 +1,15 @@ +PlanState in bdk_tmp_plan - Rust

    Enum bdk_tmp_plan::PlanState

    source ·
    pub enum PlanState<Ak> {
    +    Complete {
    +        final_script_sig: Option<Script>,
    +        final_script_witness: Option<Witness>,
    +    },
    +    Incomplete(Requirements<Ak>),
    +}
    Expand description

    The returned value from Plan::try_complete.

    +

    Variants§

    §

    Complete

    Fields

    §final_script_sig: Option<Script>

    The script sig that should be set on the input

    +
    §final_script_witness: Option<Witness>

    The witness that should be set on the input

    +

    The plan is complete

    +
    §

    Incomplete(Requirements<Ak>)

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.RequiredSignatures.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.RequiredSignatures.html new file mode 100644 index 0000000000..3593dbbf50 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.RequiredSignatures.html @@ -0,0 +1,29 @@ +RequiredSignatures in bdk_tmp_plan - Rust
    pub enum RequiredSignatures<Ak> {
    +    Legacy {
    +        keys: Vec<PlanKey<Ak>>,
    +    },
    +    Segwitv0 {
    +        keys: Vec<PlanKey<Ak>>,
    +    },
    +    TapKey {
    +        plan_key: PlanKey<Ak>,
    +        merkle_root: Option<TapBranchHash>,
    +    },
    +    TapScript {
    +        leaf_hash: TapLeafHash,
    +        plan_keys: Vec<PlanKey<Ak>>,
    +    },
    +}
    Expand description

    The signatures required to complete the plan

    +

    Variants§

    §

    Legacy

    Fields

    §keys: Vec<PlanKey<Ak>>

    Legacy ECDSA signatures are required

    +
    §

    Segwitv0

    Fields

    §keys: Vec<PlanKey<Ak>>

    Segwitv0 ECDSA signatures are required

    +
    §

    TapKey

    Fields

    §plan_key: PlanKey<Ak>

    the internal key

    +
    §merkle_root: Option<TapBranchHash>

    The merkle root of the taproot output

    +

    A Taproot key spend signature is required

    +
    §

    TapScript

    Fields

    §leaf_hash: TapLeafHash

    The leaf hash of the script being used

    +
    §plan_keys: Vec<PlanKey<Ak>>

    The keys in the script that require signatures

    +

    Taproot script path signatures are required

    +

    Implementations§

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.SigningError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.SigningError.html new file mode 100644 index 0000000000..3b044c1886 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/enum.SigningError.html @@ -0,0 +1,9 @@ +SigningError in bdk_tmp_plan - Rust
    pub enum SigningError {
    +    SigHashError(Error),
    +    DerivationError(Error),
    +}

    Variants§

    §

    SigHashError(Error)

    §

    DerivationError(Error)

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Formats the value using the given formatter. Read more
    The lower-level source of this error, if any. Read more
    👎Deprecated since 1.42.0: use the Display impl or to_string()
    👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
    🔬This is a nightly-only experimental API. (error_generic_member_access)
    Provides type based access to context intended for error reports. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    🔬This is a nightly-only experimental API. (provide_any)
    Data providers should implement this method to provide all values they are able to +provide by using demand. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/fn.plan_satisfaction.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/fn.plan_satisfaction.html new file mode 100644 index 0000000000..4327e837c5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/fn.plan_satisfaction.html @@ -0,0 +1 @@ +plan_satisfaction in bdk_tmp_plan - Rust
    pub fn plan_satisfaction<Ak>(
        desc: &Descriptor<DefiniteDescriptorKey>,
        assets: &Assets<Ak>
    ) -> Option<Plan<Ak>>where
        Ak: CanDerive + Clone,
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/index.html new file mode 100644 index 0000000000..44a87bc2ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/index.html @@ -0,0 +1,12 @@ +bdk_tmp_plan - Rust

    Crate bdk_tmp_plan

    source ·
    Expand description

    A spending plan or plan for short is a representation of a particular spending path on a +descriptor. This allows us to analayze a choice of spending path without producing any +signatures or other witness data for it.

    +

    To make a plan you provide the descriptor with “assets” like which keys you are able to use, hash +pre-images you have access to, the current block height etc.

    +

    Once you’ve got a plan it can tell you its expected satisfaction weight which can be useful for +doing coin selection. Furthermore it provides which subset of those keys and hash pre-images you +will actually need as well as what locktime or sequence number you need to set.

    +

    Once you’ve obstained signatures, hash pre-images etc required by the plan, it can create a +witness/script_sig for the input.

    +

    Structs

    A plan represents a particular spending path for a descriptor.
    A plan key contains the asset key originally provided along with key in the descriptor it +purports to be able to derive for along with a “hint” on how to derive it.
    Signatures and hash pre-images that must be provided to complete the plan.
    Signatures and hash pre-images that can be used to complete a plan.

    Enums

    The returned value from Plan::try_complete.
    The signatures required to complete the plan

    Traits

    Functions

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/enum.RequiredSignatures.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/enum.RequiredSignatures.html new file mode 100644 index 0000000000..a74fe13ded --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/enum.RequiredSignatures.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_tmp_plan/enum.RequiredSignatures.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/enum.SigningError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/enum.SigningError.html new file mode 100644 index 0000000000..83d223931e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/enum.SigningError.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_tmp_plan/enum.SigningError.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/struct.Requirements.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/struct.Requirements.html new file mode 100644 index 0000000000..7bc1519a49 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/requirements/struct.Requirements.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_tmp_plan/struct.Requirements.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/sidebar-items.js new file mode 100644 index 0000000000..5dcb351bd4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["PlanState","The returned value from [`Plan::try_complete`]."],["RequiredSignatures","The signatures required to complete the plan"],["SigningError",""]],"fn":[["plan_satisfaction",""]],"struct":[["Assets",""],["Plan","A plan represents a particular spending path for a descriptor."],["PlanKey","A plan key contains the asset key originally provided along with key in the descriptor it purports to be able to derive for along with a “hint” on how to derive it."],["Requirements","Signatures and hash pre-images that must be provided to complete the plan."],["SatisfactionMaterial","Signatures and hash pre-images that can be used to complete a plan."]],"trait":[["CanDerive",""]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Assets.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Assets.html new file mode 100644 index 0000000000..91be5a4595 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Assets.html @@ -0,0 +1,13 @@ +Assets in bdk_tmp_plan - Rust

    Struct bdk_tmp_plan::Assets

    source ·
    pub struct Assets<K> {
    +    pub keys: Vec<K>,
    +    pub txo_age: Option<Sequence>,
    +    pub max_locktime: Option<LockTime>,
    +    pub sha256: Vec<Hash>,
    +    pub hash256: Vec<Hash>,
    +    pub ripemd160: Vec<Hash>,
    +    pub hash160: Vec<Hash>,
    +}

    Fields§

    §keys: Vec<K>§txo_age: Option<Sequence>§max_locktime: Option<LockTime>§sha256: Vec<Hash>§hash256: Vec<Hash>§ripemd160: Vec<Hash>§hash160: Vec<Hash>

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Plan.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Plan.html new file mode 100644 index 0000000000..3d537e4a86 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Plan.html @@ -0,0 +1,12 @@ +Plan in bdk_tmp_plan - Rust

    Struct bdk_tmp_plan::Plan

    source ·
    pub struct Plan<AK> { /* private fields */ }
    Expand description

    A plan represents a particular spending path for a descriptor.

    +

    See the module level documentation for more info.

    +

    Implementations§

    The expected satisfaction weight for the plan if it is completed.

    +

    Witness version for the plan

    +

    The minimum required locktime height or time on the transaction using the plan.

    +

    The minimum required sequence (height or time) on the input to satisfy the plan

    +

    The minmum required transaction version required on the transaction using the plan.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.PlanKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.PlanKey.html new file mode 100644 index 0000000000..a539e7ac48 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.PlanKey.html @@ -0,0 +1,15 @@ +PlanKey in bdk_tmp_plan - Rust

    Struct bdk_tmp_plan::PlanKey

    source ·
    pub struct PlanKey<Ak> {
    +    pub asset_key: Ak,
    +    pub derivation_hint: DerivationPath,
    +    pub descriptor_key: DefiniteDescriptorKey,
    +}
    Expand description

    A plan key contains the asset key originally provided along with key in the descriptor it +purports to be able to derive for along with a “hint” on how to derive it.

    +

    Fields§

    §asset_key: Ak

    The key the planner will sign with

    +
    §derivation_hint: DerivationPath

    A hint from how to get from the asset key to the concrete key we need to sign with.

    +
    §descriptor_key: DefiniteDescriptorKey

    The key that was in the descriptor that we are satisfying with the signature from the asset +key.

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Requirements.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Requirements.html new file mode 100644 index 0000000000..b2422fef45 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.Requirements.html @@ -0,0 +1,18 @@ +Requirements in bdk_tmp_plan - Rust

    Struct bdk_tmp_plan::Requirements

    source ·
    pub struct Requirements<Ak> {
    +    pub signatures: RequiredSignatures<Ak>,
    +    pub sha256_images: HashSet<Hash>,
    +    pub hash160_images: HashSet<Hash>,
    +    pub hash256_images: HashSet<Hash>,
    +    pub ripemd160_images: HashSet<Hash>,
    +}
    Expand description

    Signatures and hash pre-images that must be provided to complete the plan.

    +

    Fields§

    §signatures: RequiredSignatures<Ak>

    required signatures

    +
    §sha256_images: HashSet<Hash>

    required sha256 pre-images

    +
    §hash160_images: HashSet<Hash>

    required hash160 pre-images

    +
    §hash256_images: HashSet<Hash>

    required hash256 pre-images

    +
    §ripemd160_images: HashSet<Hash>

    required ripemd160 pre-images

    +

    Implementations§

    Whether any hash pre-images are required in the plan

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.SatisfactionMaterial.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.SatisfactionMaterial.html new file mode 100644 index 0000000000..6f5a93e246 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/struct.SatisfactionMaterial.html @@ -0,0 +1,19 @@ +SatisfactionMaterial in bdk_tmp_plan - Rust
    pub struct SatisfactionMaterial {
    +    pub schnorr_sigs: BTreeMap<DefiniteDescriptorKey, SchnorrSig>,
    +    pub ecdsa_sigs: BTreeMap<DefiniteDescriptorKey, EcdsaSig>,
    +    pub sha256_preimages: BTreeMap<Hash, Vec<u8>>,
    +    pub hash160_preimages: BTreeMap<Hash, Vec<u8>>,
    +    pub hash256_preimages: BTreeMap<Hash, Vec<u8>>,
    +    pub ripemd160_preimages: BTreeMap<Hash, Vec<u8>>,
    +}
    Expand description

    Signatures and hash pre-images that can be used to complete a plan.

    +

    Fields§

    §schnorr_sigs: BTreeMap<DefiniteDescriptorKey, SchnorrSig>

    Schnorr signautres under their keys

    +
    §ecdsa_sigs: BTreeMap<DefiniteDescriptorKey, EcdsaSig>

    ECDSA signatures under their keys

    +
    §sha256_preimages: BTreeMap<Hash, Vec<u8>>

    SHA256 pre-images under their images

    +
    §hash160_preimages: BTreeMap<Hash, Vec<u8>>

    hash160 pre-images under their images

    +
    §hash256_preimages: BTreeMap<Hash, Vec<u8>>

    hash256 pre-images under their images

    +
    §ripemd160_preimages: BTreeMap<Hash, Vec<u8>>

    ripemd160 pre-images under their images

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/template/struct.PlanKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/template/struct.PlanKey.html new file mode 100644 index 0000000000..a3953301e9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/template/struct.PlanKey.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

    Redirecting to ../../bdk_tmp_plan/struct.PlanKey.html...

    + + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/trait.CanDerive.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/trait.CanDerive.html new file mode 100644 index 0000000000..8e127b3357 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_tmp_plan/trait.CanDerive.html @@ -0,0 +1,3 @@ +CanDerive in bdk_tmp_plan - Rust

    Trait bdk_tmp_plan::CanDerive

    source ·
    pub trait CanDerive {
    +    fn can_derive(&self, key: &DefiniteDescriptorKey) -> Option<DerivationPath>;
    +}

    Required Methods§

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/crates.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/crates.js index 0abc2ef87a..5930ee8a62 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/crates.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/crates.js @@ -1 +1 @@ -window.ALL_CRATES = ["bdk"]; \ No newline at end of file +window.ALL_CRATES = ["bdk","bdk_chain","bdk_coin_select","bdk_electrum","bdk_esplora","bdk_esplora_wallet_example","bdk_file_store","bdk_tmp_plan","keychain_tracker_electrum_example","keychain_tracker_esplora_example","keychain_tracker_example_cli","wallet_electrum_example","wallet_esplora_async"]; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/help.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/help.html index 700c7c3d65..8659dfcc0d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/help.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/help.html @@ -1,2 +1 @@ -Rustdoc help

    Rustdoc help

    Back
    \ No newline at end of file +Rustdoc help

    Rustdoc help

    Back
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.BlockchainFactory.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.BlockchainFactory.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.BlockchainFactory.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetBlockHash.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetBlockHash.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetBlockHash.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetHeight.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetHeight.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetHeight.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetTx.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetTx.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.GetTx.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.StatelessBlockchain.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.StatelessBlockchain.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.StatelessBlockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.WalletSync.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.WalletSync.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.WalletSync.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/descriptor_ext/trait.DescriptorExt.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/descriptor_ext/trait.DescriptorExt.js new file mode 100644 index 0000000000..1a8211de1a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/descriptor_ext/trait.DescriptorExt.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_chain":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/keychain/persist/trait.PersistBackend.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/keychain/persist/trait.PersistBackend.js new file mode 100644 index 0000000000..a67e7a7969 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/keychain/persist/trait.PersistBackend.js @@ -0,0 +1,4 @@ +(function() {var implementors = { +"bdk_chain":[], +"bdk_file_store":[["impl<K, P> PersistBackend<K, P> for KeychainStore<K, P>where
        K: Ord + Clone + Debug,
        P: ChainPosition,
        KeychainChangeSet<K, P>: Serialize + DeserializeOwned,
    "]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/sparse_chain/trait.ChainPosition.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/sparse_chain/trait.ChainPosition.js new file mode 100644 index 0000000000..1a8211de1a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/sparse_chain/trait.ChainPosition.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_chain":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.ForEachTxOut.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.ForEachTxOut.js new file mode 100644 index 0000000000..1a8211de1a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.ForEachTxOut.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_chain":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_electrum/trait.ElectrumExt.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_electrum/trait.ElectrumExt.js new file mode 100644 index 0000000000..11e040008a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_electrum/trait.ElectrumExt.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_electrum":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_esplora/async_ext/trait.EsploraAsyncExt.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_esplora/async_ext/trait.EsploraAsyncExt.js new file mode 100644 index 0000000000..1f4be89de9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_esplora/async_ext/trait.EsploraAsyncExt.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_esplora":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_esplora/blocking_ext/trait.EsploraExt.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_esplora/blocking_ext/trait.EsploraExt.js new file mode 100644 index 0000000000..1f4be89de9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_esplora/blocking_ext/trait.EsploraExt.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_esplora":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_tmp_plan/trait.CanDerive.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_tmp_plan/trait.CanDerive.js new file mode 100644 index 0000000000..d955c83b6e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_tmp_plan/trait.CanDerive.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_tmp_plan":[] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Args.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Args.js new file mode 100644 index 0000000000..a45f21567b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Args.js @@ -0,0 +1,5 @@ +(function() {var implementors = { +"keychain_tracker_electrum_example":[["impl Args for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl Args for ScanOptions"]], +"keychain_tracker_example_cli":[["impl<C: Subcommand> Args for Args<C>"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.CommandFactory.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.CommandFactory.js new file mode 100644 index 0000000000..4c44dd3681 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.CommandFactory.js @@ -0,0 +1,5 @@ +(function() {var implementors = { +"keychain_tracker_electrum_example":[["impl CommandFactory for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl CommandFactory for ScanOptions"]], +"keychain_tracker_example_cli":[["impl<C: Subcommand> CommandFactory for Args<C>"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.FromArgMatches.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.FromArgMatches.js new file mode 100644 index 0000000000..7d96cca136 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.FromArgMatches.js @@ -0,0 +1,5 @@ +(function() {var implementors = { +"keychain_tracker_electrum_example":[["impl FromArgMatches for ElectrumCommands"],["impl FromArgMatches for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl FromArgMatches for EsploraCommands"],["impl FromArgMatches for ScanOptions"]], +"keychain_tracker_example_cli":[["impl<C: Subcommand> FromArgMatches for Args<C>"],["impl<C: Subcommand> FromArgMatches for Commands<C>"],["impl FromArgMatches for AddressCmd"],["impl FromArgMatches for TxOutCmd"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Parser.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Parser.js new file mode 100644 index 0000000000..0a70855e9f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Parser.js @@ -0,0 +1,5 @@ +(function() {var implementors = { +"keychain_tracker_electrum_example":[["impl Parser for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl Parser for ScanOptions"]], +"keychain_tracker_example_cli":[["impl<C: Subcommand> Parser for Args<C>"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Subcommand.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Subcommand.js new file mode 100644 index 0000000000..736dec0f24 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/clap/derive/trait.Subcommand.js @@ -0,0 +1,5 @@ +(function() {var implementors = { +"keychain_tracker_electrum_example":[["impl Subcommand for ElectrumCommands"]], +"keychain_tracker_esplora_example":[["impl Subcommand for EsploraCommands"]], +"keychain_tracker_example_cli":[["impl<C: Subcommand> Subcommand for Commands<C>"],["impl Subcommand for AddressCmd"],["impl Subcommand for TxOutCmd"]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js index f9f37ca62e..7b9d2d5d98 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js @@ -1,3 +1,9 @@ (function() {var implementors = { -"bdk":[["impl Clone for AnyBlockchainConfig"],["impl Clone for ElectrumBlockchainConfig"],["impl Clone for RpcConfig"],["impl Clone for RpcSyncParams"],["impl Clone for Auth"],["impl Clone for RpcBlockchainFactory"],["impl Clone for EsploraBlockchainConfig"],["impl Clone for BitcoinPeerConfig"],["impl Clone for CompactFiltersBlockchainConfig"],["impl Clone for Capability"],["impl Clone for NoopProgress"],["impl Clone for LogProgress"],["impl Clone for SyncTime"],["impl Clone for PkOrF"],["impl Clone for SatisfiableItem"],["impl Clone for Satisfaction"],["impl Clone for Policy"],["impl Clone for Condition"],["impl<'a> Clone for BuildSatisfaction<'a>"],["impl Clone for ScriptContextEnum"],["impl<K: Clone, Ctx: ScriptContext> Clone for GeneratedKey<K, Ctx>"],["impl Clone for PrivateKeyGenerateOptions"],["impl Clone for KeychainKind"],["impl Clone for FeeRate"],["impl Clone for LocalUtxo"],["impl Clone for WeightedUtxo"],["impl Clone for Utxo"],["impl Clone for TransactionDetails"],["impl Clone for BlockTime"],["impl Clone for Balance"],["impl Clone for LargestFirstCoinSelection"],["impl Clone for OldestFirstCoinSelection"],["impl Clone for SignerId"],["impl Clone for SignerError"],["impl Clone for SignerContext"],["impl<S: Clone + Sized + Debug + Clone> Clone for SignerWrapper<S>"],["impl Clone for SignerOrdering"],["impl Clone for SignersContainer"],["impl Clone for SignOptions"],["impl Clone for TapLeavesOptions"],["impl Clone for CreateTx"],["impl Clone for BumpFee"],["impl<'a, Cs: Clone, Ctx, D> Clone for TxBuilder<'a, D, Cs, Ctx>"],["impl Clone for TxOrdering"],["impl Clone for ChangeSpendPolicy"]] +"bdk":[["impl Clone for PkOrF"],["impl Clone for SatisfiableItem"],["impl Clone for Satisfaction"],["impl Clone for Policy"],["impl Clone for Condition"],["impl<'a> Clone for BuildSatisfaction<'a>"],["impl Clone for ScriptContextEnum"],["impl<K: Clone, Ctx: ScriptContext> Clone for GeneratedKey<K, Ctx>"],["impl Clone for PrivateKeyGenerateOptions"],["impl Clone for KeychainKind"],["impl Clone for FeeRate"],["impl Clone for LocalUtxo"],["impl Clone for WeightedUtxo"],["impl Clone for Utxo"],["impl Clone for TransactionDetails"],["impl Clone for LargestFirstCoinSelection"],["impl Clone for OldestFirstCoinSelection"],["impl Clone for BranchAndBoundCoinSelection"],["impl Clone for SignerId"],["impl Clone for SignerError"],["impl Clone for SignerContext"],["impl<S: Clone + Sized + Debug + Clone> Clone for SignerWrapper<S>"],["impl Clone for SignerOrdering"],["impl Clone for SignersContainer"],["impl Clone for SignOptions"],["impl Clone for TapLeavesOptions"],["impl Clone for CreateTx"],["impl Clone for BumpFee"],["impl<'a, D, Cs: Clone, Ctx> Clone for TxBuilder<'a, D, Cs, Ctx>"],["impl Clone for TxOrdering"],["impl Clone for ChangeSpendPolicy"]], +"bdk_chain":[["impl<P: Clone> Clone for ChainGraph<P>"],["impl<P: Clone> Clone for ChangeSet<P>"],["impl<P: Clone> Clone for NewError<P>"],["impl<P: Clone> Clone for InsertTxError<P>"],["impl<P: Clone> Clone for UpdateError<P>"],["impl<P: Clone> Clone for UnresolvableConflict<P>"],["impl<I: Clone> Clone for SpkTxOutIndex<I>"],["impl Clone for TxHeight"],["impl Clone for ConfirmationTime"],["impl Clone for BlockId"],["impl<I: Clone> Clone for FullTxOut<I>"],["impl<K: Clone, P: Clone> Clone for KeychainTracker<K, P>"],["impl<K: Clone> Clone for KeychainTxOutIndex<K>"],["impl<K: Clone> Clone for DerivationAdditions<K>"],["impl<K: Clone, P: Clone> Clone for KeychainScan<K, P>"],["impl<K: Clone, P: Clone> Clone for KeychainChangeSet<K, P>"],["impl Clone for Balance"],["impl<P: Clone> Clone for SparseChain<P>"],["impl<P: Clone> Clone for InsertTxError<P>"],["impl Clone for InsertCheckpointError"],["impl<P: Clone> Clone for UpdateError<P>"],["impl<P: Clone> Clone for ChangeSet<P>"],["impl Clone for TxGraph"],["impl Clone for Additions"]], +"bdk_coin_select":[["impl Clone for WeightedValue"],["impl Clone for CoinSelectorOpt"],["impl<'a> Clone for CoinSelector<'a>"],["impl Clone for SelectionError"],["impl Clone for SelectionConstraint"],["impl Clone for Selection"],["impl Clone for ExcessStrategyKind"],["impl Clone for ExcessStrategy"]], +"bdk_tmp_plan":[["impl<Ak: Clone> Clone for Requirements<Ak>"],["impl<Ak: Clone> Clone for RequiredSignatures<Ak>"],["impl Clone for SigningError"],["impl<Ak: Clone> Clone for PlanKey<Ak>"],["impl<AK: Clone> Clone for Plan<AK>"],["impl Clone for SatisfactionMaterial"],["impl<K: Clone> Clone for Assets<K>"]], +"keychain_tracker_electrum_example":[["impl Clone for ElectrumCommands"],["impl Clone for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl Clone for EsploraCommands"],["impl Clone for ScanOptions"]], +"keychain_tracker_example_cli":[["impl<C: Clone + Subcommand> Clone for Commands<C>"],["impl Clone for CoinSelectionAlgo"],["impl Clone for AddressCmd"],["impl Clone for TxOutCmd"],["impl Clone for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js index d4b5e911c3..cf17e91c08 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js @@ -1,3 +1,6 @@ (function() {var implementors = { -"bdk":[["impl Eq for AnyBlockchainConfig"],["impl Eq for ElectrumBlockchainConfig"],["impl Eq for RpcConfig"],["impl Eq for RpcSyncParams"],["impl Eq for Auth"],["impl Eq for EsploraBlockchainConfig"],["impl Eq for BitcoinPeerConfig"],["impl Eq for CompactFiltersBlockchainConfig"],["impl Eq for Capability"],["impl Eq for SyncTime"],["impl Eq for PkOrF"],["impl Eq for SatisfiableItem"],["impl Eq for Satisfaction"],["impl Eq for Policy"],["impl Eq for Condition"],["impl Eq for PolicyError"],["impl Eq for ScriptContextEnum"],["impl Eq for KeychainKind"],["impl Eq for LocalUtxo"],["impl Eq for WeightedUtxo"],["impl Eq for Utxo"],["impl Eq for TransactionDetails"],["impl Eq for BlockTime"],["impl Eq for Balance"],["impl Eq for SignerId"],["impl Eq for SignerError"],["impl Eq for SignerContext"],["impl Eq for SignerOrdering"],["impl Eq for TapLeavesOptions"],["impl Eq for TxOrdering"],["impl Eq for ChangeSpendPolicy"],["impl Eq for AddressInfo"]] +"bdk":[["impl Eq for PkOrF"],["impl Eq for SatisfiableItem"],["impl Eq for Satisfaction"],["impl Eq for Policy"],["impl Eq for Condition"],["impl Eq for PolicyError"],["impl Eq for ScriptContextEnum"],["impl Eq for KeychainKind"],["impl Eq for LocalUtxo"],["impl Eq for WeightedUtxo"],["impl Eq for Utxo"],["impl Eq for TransactionDetails"],["impl Eq for SignerId"],["impl Eq for SignerError"],["impl Eq for SignerContext"],["impl Eq for SignerOrdering"],["impl Eq for TapLeavesOptions"],["impl Eq for TxOrdering"],["impl Eq for ChangeSpendPolicy"],["impl Eq for AddressInfo"]], +"bdk_chain":[["impl Eq for TxHeight"],["impl Eq for ConfirmationTime"],["impl Eq for BlockId"],["impl Eq for Balance"]], +"bdk_coin_select":[["impl Eq for SelectionConstraint"],["impl Eq for ExcessStrategyKind"]], +"keychain_tracker_example_cli":[["impl Eq for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js index 5a709cc30b..2528266e74 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js @@ -1,3 +1,6 @@ (function() {var implementors = { -"bdk":[["impl Ord for Auth"],["impl Ord for TransactionDetails"],["impl Ord for BlockTime"],["impl Ord for SignerId"],["impl Ord for SignerOrdering"],["impl Ord for TxOrdering"],["impl Ord for ChangeSpendPolicy"]] +"bdk":[["impl Ord for KeychainKind"],["impl Ord for TransactionDetails"],["impl Ord for SignerId"],["impl Ord for SignerOrdering"],["impl Ord for TxOrdering"],["impl Ord for ChangeSpendPolicy"]], +"bdk_chain":[["impl Ord for TxHeight"],["impl Ord for ConfirmationTime"],["impl Ord for BlockId"]], +"bdk_coin_select":[["impl Ord for ExcessStrategyKind"]], +"keychain_tracker_example_cli":[["impl Ord for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js index ae3fa73075..075118c0b1 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js @@ -1,3 +1,8 @@ (function() {var implementors = { -"bdk":[["impl PartialEq<AnyBlockchainConfig> for AnyBlockchainConfig"],["impl PartialEq<ElectrumBlockchainConfig> for ElectrumBlockchainConfig"],["impl PartialEq<RpcConfig> for RpcConfig"],["impl PartialEq<RpcSyncParams> for RpcSyncParams"],["impl PartialEq<Auth> for Auth"],["impl PartialEq<EsploraBlockchainConfig> for EsploraBlockchainConfig"],["impl PartialEq<BitcoinPeerConfig> for BitcoinPeerConfig"],["impl PartialEq<CompactFiltersBlockchainConfig> for CompactFiltersBlockchainConfig"],["impl PartialEq<Capability> for Capability"],["impl PartialEq<SyncTime> for SyncTime"],["impl PartialEq<PkOrF> for PkOrF"],["impl PartialEq<SatisfiableItem> for SatisfiableItem"],["impl PartialEq<Satisfaction> for Satisfaction"],["impl PartialEq<Policy> for Policy"],["impl PartialEq<Condition> for Condition"],["impl PartialEq<PolicyError> for PolicyError"],["impl PartialEq<ScriptContextEnum> for ScriptContextEnum"],["impl PartialEq<KeychainKind> for KeychainKind"],["impl PartialEq<FeeRate> for FeeRate"],["impl PartialEq<LocalUtxo> for LocalUtxo"],["impl PartialEq<WeightedUtxo> for WeightedUtxo"],["impl PartialEq<Utxo> for Utxo"],["impl PartialEq<TransactionDetails> for TransactionDetails"],["impl PartialEq<BlockTime> for BlockTime"],["impl PartialEq<Balance> for Balance"],["impl PartialEq<SignerId> for SignerId"],["impl PartialEq<SignerError> for SignerError"],["impl PartialEq<SignerContext> for SignerContext"],["impl PartialEq<SignerOrdering> for SignerOrdering"],["impl PartialEq<TapLeavesOptions> for TapLeavesOptions"],["impl PartialEq<TxOrdering> for TxOrdering"],["impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy"],["impl PartialEq<AddressInfo> for AddressInfo"]] +"bdk":[["impl PartialEq<PkOrF> for PkOrF"],["impl PartialEq<SatisfiableItem> for SatisfiableItem"],["impl PartialEq<Satisfaction> for Satisfaction"],["impl PartialEq<Policy> for Policy"],["impl PartialEq<Condition> for Condition"],["impl PartialEq<PolicyError> for PolicyError"],["impl PartialEq<ScriptContextEnum> for ScriptContextEnum"],["impl PartialEq<KeychainKind> for KeychainKind"],["impl PartialEq<FeeRate> for FeeRate"],["impl PartialEq<LocalUtxo> for LocalUtxo"],["impl PartialEq<WeightedUtxo> for WeightedUtxo"],["impl PartialEq<Utxo> for Utxo"],["impl PartialEq<TransactionDetails> for TransactionDetails"],["impl PartialEq<SignerId> for SignerId"],["impl PartialEq<SignerError> for SignerError"],["impl PartialEq<SignerContext> for SignerContext"],["impl PartialEq<SignerOrdering> for SignerOrdering"],["impl PartialEq<TapLeavesOptions> for TapLeavesOptions"],["impl PartialEq<TxOrdering> for TxOrdering"],["impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy"],["impl PartialEq<AddressInfo> for AddressInfo"]], +"bdk_chain":[["impl<P: PartialEq> PartialEq<ChainGraph<P>> for ChainGraph<P>"],["impl<P: PartialEq> PartialEq<ChangeSet<P>> for ChangeSet<P>"],["impl<P: PartialEq> PartialEq<NewError<P>> for NewError<P>"],["impl<P: PartialEq> PartialEq<InsertTxError<P>> for InsertTxError<P>"],["impl<P: PartialEq> PartialEq<UpdateError<P>> for UpdateError<P>"],["impl<P: PartialEq> PartialEq<UnresolvableConflict<P>> for UnresolvableConflict<P>"],["impl PartialEq<TxHeight> for TxHeight"],["impl PartialEq<ConfirmationTime> for ConfirmationTime"],["impl PartialEq<BlockId> for BlockId"],["impl<I: PartialEq> PartialEq<FullTxOut<I>> for FullTxOut<I>"],["impl<K: PartialEq> PartialEq<DerivationAdditions<K>> for DerivationAdditions<K>"],["impl<K: PartialEq, P: PartialEq> PartialEq<KeychainScan<K, P>> for KeychainScan<K, P>"],["impl PartialEq<Balance> for Balance"],["impl<P: PartialEq> PartialEq<SparseChain<P>> for SparseChain<P>"],["impl<P: PartialEq> PartialEq<InsertTxError<P>> for InsertTxError<P>"],["impl PartialEq<InsertCheckpointError> for InsertCheckpointError"],["impl<P: PartialEq> PartialEq<UpdateError<P>> for UpdateError<P>"],["impl<P: PartialEq> PartialEq<ChangeSet<P>> for ChangeSet<P>"],["impl PartialEq<TxGraph> for TxGraph"],["impl PartialEq<Additions> for Additions"]], +"bdk_coin_select":[["impl PartialEq<SelectionConstraint> for SelectionConstraint"],["impl PartialEq<ExcessStrategyKind> for ExcessStrategyKind"]], +"keychain_tracker_electrum_example":[["impl PartialEq<ScanOptions> for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl PartialEq<ScanOptions> for ScanOptions"]], +"keychain_tracker_example_cli":[["impl PartialEq<Keychain> for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js index 2bb0622cc3..7fc8d3fdde 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js @@ -1,3 +1,6 @@ (function() {var implementors = { -"bdk":[["impl PartialOrd<Auth> for Auth"],["impl PartialOrd<Condition> for Condition"],["impl PartialOrd<FeeRate> for FeeRate"],["impl PartialOrd<TransactionDetails> for TransactionDetails"],["impl PartialOrd<BlockTime> for BlockTime"],["impl PartialOrd<SignerId> for SignerId"],["impl PartialOrd<SignerOrdering> for SignerOrdering"],["impl PartialOrd<TxOrdering> for TxOrdering"],["impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy"]] +"bdk":[["impl PartialOrd<Condition> for Condition"],["impl PartialOrd<KeychainKind> for KeychainKind"],["impl PartialOrd<FeeRate> for FeeRate"],["impl PartialOrd<TransactionDetails> for TransactionDetails"],["impl PartialOrd<SignerId> for SignerId"],["impl PartialOrd<SignerOrdering> for SignerOrdering"],["impl PartialOrd<TxOrdering> for TxOrdering"],["impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy"]], +"bdk_chain":[["impl PartialOrd<TxHeight> for TxHeight"],["impl PartialOrd<ConfirmationTime> for ConfirmationTime"],["impl PartialOrd<BlockId> for BlockId"]], +"bdk_coin_select":[["impl PartialOrd<ExcessStrategyKind> for ExcessStrategyKind"]], +"keychain_tracker_example_cli":[["impl PartialOrd<Keychain> for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js index cfe2be8162..78f9f3865e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js @@ -1,3 +1,5 @@ (function() {var implementors = { -"bdk":[["impl AsRef<[u8]> for KeychainKind"]] +"bdk":[["impl AsRef<[u8]> for KeychainKind"],["impl<D> AsRef<TxGraph> for Wallet<D>"],["impl<D> AsRef<ChainGraph<ConfirmationTime>> for Wallet<D>"]], +"bdk_chain":[["impl<P> AsRef<SparseChain<P>> for ChainGraph<P>"],["impl<P> AsRef<TxGraph> for ChainGraph<P>"],["impl<P> AsRef<ChainGraph<P>> for ChainGraph<P>"],["impl<K, P> AsRef<SparseChain<P>> for KeychainTracker<K, P>"],["impl<K, P> AsRef<TxGraph> for KeychainTracker<K, P>"],["impl<K, P> AsRef<ChainGraph<P>> for KeychainTracker<K, P>"],["impl<K> AsRef<BTreeMap<K, u32, Global>> for DerivationAdditions<K>"],["impl<K, P> AsRef<TxGraph> for KeychainScan<K, P>"],["impl<P> AsRef<SparseChain<P>> for SparseChain<P>"],["impl AsRef<TxGraph> for TxGraph"]], +"bdk_electrum":[["impl<K, P> AsRef<SparseChain<P>> for ElectrumUpdate<K, P>"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js index b4d7af8d22..f23f8bb67b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js @@ -1,3 +1,7 @@ (function() {var implementors = { -"bdk":[["impl From<Error> for Error"],["impl From<PolicyError> for Error"],["impl From<SignerError> for Error"],["impl From<KeyError> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<PsbtParseError> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<CompactFiltersError> for Error"],["impl From<VerifyError> for Error"],["impl From<Error> for Error"],["impl From<ElectrumBlockchain> for AnyBlockchain"],["impl From<EsploraBlockchain> for AnyBlockchain"],["impl From<CompactFiltersBlockchain> for AnyBlockchain"],["impl From<RpcBlockchain> for AnyBlockchain"],["impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig"],["impl From<EsploraBlockchainConfig> for AnyBlockchainConfig"],["impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig"],["impl From<RpcConfig> for AnyBlockchainConfig"],["impl From<Client> for ElectrumBlockchain"],["impl From<Auth> for RpcAuth"],["impl From<BlockTime> for BlockTime"],["impl From<Error> for CompactFiltersError"],["impl From<Error> for CompactFiltersError"],["impl From<Error> for CompactFiltersError"],["impl From<SystemTimeError> for CompactFiltersError"],["impl From<Error> for CompactFiltersError"],["impl From<MemoryDatabase> for AnyDatabase"],["impl From<Tree> for AnyDatabase"],["impl From<SqliteDatabase> for AnyDatabase"],["impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch"],["impl From<<Tree as BatchDatabase>::Batch> for AnyBatch"],["impl From<<SqliteDatabase as BatchDatabase>::Batch> for AnyBatch"],["impl From<()> for AnyDatabaseConfig"],["impl From<SledDbConfiguration> for AnyDatabaseConfig"],["impl From<SqliteDbConfiguration> for AnyDatabaseConfig"],["impl From<KeyError> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<PolicyError> for Error"],["impl From<bool> for Satisfaction"],["impl From<SatisfiableItem> for Policy"],["impl<Ctx: ScriptContext> From<ExtendedPubKey> for ExtendedKey<Ctx>"],["impl<Ctx: ScriptContext> From<ExtendedPrivKey> for ExtendedKey<Ctx>"],["impl From<Error> for KeyError"],["impl From<Error> for KeyError"],["impl From<Hash> for SignerId"],["impl From<Fingerprint> for SignerId"],["impl From<Error> for SignerError"],["impl From<Error> for SignerError"],["impl From<Error> for VerifyError"],["impl From<Error> for VerifyError"]] +"bdk":[["impl From<Error> for Error"],["impl From<PolicyError> for Error"],["impl From<SignerError> for Error"],["impl From<KeyError> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<KeyError> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<PolicyError> for Error"],["impl From<bool> for Satisfaction"],["impl From<SatisfiableItem> for Policy"],["impl<Ctx: ScriptContext> From<ExtendedPubKey> for ExtendedKey<Ctx>"],["impl<Ctx: ScriptContext> From<ExtendedPrivKey> for ExtendedKey<Ctx>"],["impl From<Error> for KeyError"],["impl From<Error> for KeyError"],["impl From<Hash> for SignerId"],["impl From<Fingerprint> for SignerId"],["impl From<Error> for SignerError"]], +"bdk_chain":[["impl<P> From<InsertTxError<P>> for InsertTxError<P>"],["impl<P> From<UpdateError<P>> for UpdateError<P>"],["impl<P> From<UnresolvableConflict<P>> for UpdateError<P>"],["impl<P> From<UnresolvableConflict<P>> for InsertTxError<P>"],["impl From<Option<u32>> for TxHeight"],["impl From<TxHeight> for Option<u32>"],["impl From<(u32, BlockHash)> for BlockId"],["impl From<BlockId> for (u32, BlockHash)"],["impl From<(&u32, &BlockHash)> for BlockId"],["impl<K, P> From<ChainGraph<P>> for KeychainScan<K, P>"],["impl<K, P> From<ChangeSet<P>> for KeychainChangeSet<K, P>"],["impl<K, P> From<DerivationAdditions<K>> for KeychainChangeSet<K, P>"]], +"bdk_coin_select":[["impl From<usize> for BnbLimit"],["impl From<Duration> for BnbLimit"]], +"bdk_file_store":[["impl From<Error> for FileError"],["impl From<Error> for IterError"]], +"bdk_tmp_plan":[["impl From<Error> for SigningError"],["impl From<Error> for SigningError"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js index a17b9ff950..c334df796e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js @@ -1,3 +1,7 @@ (function() {var implementors = { -"bdk":[["impl Default for RpcSyncParams"],["impl Default for Mempool"],["impl Default for NoopProgress"],["impl Default for LogProgress"],["impl Default for MemoryDatabase"],["impl Default for Condition"],["impl Default for PrivateKeyGenerateOptions"],["impl Default for FeeRate"],["impl Default for BlockTime"],["impl Default for Balance"],["impl Default for LargestFirstCoinSelection"],["impl Default for OldestFirstCoinSelection"],["impl Default for BranchAndBoundCoinSelection"],["impl Default for SignerOrdering"],["impl Default for SignersContainer"],["impl Default for TapLeavesOptions"],["impl Default for SignOptions"],["impl Default for CreateTx"],["impl Default for BumpFee"],["impl Default for TxOrdering"],["impl Default for ChangeSpendPolicy"],["impl Default for SyncOptions"]] +"bdk":[["impl Default for Condition"],["impl Default for PrivateKeyGenerateOptions"],["impl Default for FeeRate"],["impl Default for LargestFirstCoinSelection"],["impl Default for OldestFirstCoinSelection"],["impl Default for BranchAndBoundCoinSelection"],["impl Default for SignerOrdering"],["impl Default for SignersContainer"],["impl Default for TapLeavesOptions"],["impl Default for SignOptions"],["impl Default for CreateTx"],["impl Default for BumpFee"],["impl Default for TxOrdering"],["impl Default for ChangeSpendPolicy"]], +"bdk_chain":[["impl<P> Default for ChainGraph<P>"],["impl<P> Default for ChangeSet<P>"],["impl<I> Default for SpkTxOutIndex<I>"],["impl Default for TxHeight"],["impl Default for BlockId"],["impl<K, P> Default for KeychainTracker<K, P>"],["impl<K> Default for KeychainTxOutIndex<K>"],["impl<K> Default for DerivationAdditions<K>"],["impl<K, P> Default for KeychainScan<K, P>"],["impl<K, P> Default for KeychainChangeSet<K, P>"],["impl Default for Balance"],["impl<P> Default for SparseChain<P>"],["impl<I> Default for ChangeSet<I>"],["impl Default for TxGraph"],["impl Default for Additions"]], +"bdk_electrum":[["impl<K, P> Default for ElectrumUpdate<K, P>"]], +"bdk_tmp_plan":[["impl<Ak> Default for RequiredSignatures<Ak>"],["impl<Ak> Default for Requirements<Ak>"],["impl Default for SatisfactionMaterial"],["impl<K> Default for Assets<K>"]], +"keychain_tracker_example_cli":[["impl Default for CoinSelectionAlgo"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/error/trait.Error.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/error/trait.Error.js index 4d50be53a6..8d4e9585db 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/error/trait.Error.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/error/trait.Error.js @@ -1,3 +1,7 @@ (function() {var implementors = { -"bdk":[["impl Error for Error"],["impl Error for CompactFiltersError"],["impl Error for Error"],["impl Error for PolicyError"],["impl Error for KeyError"],["impl Error for SignerError"],["impl Error for VerifyError"]] +"bdk":[["impl Error for Error"],["impl Error for Error"],["impl Error for PolicyError"],["impl Error for KeyError"],["impl Error for SignerError"],["impl<P: Display + Debug> Error for NewError<P>"]], +"bdk_chain":[["impl<P: Debug> Error for NewError<P>"],["impl<P: Debug> Error for InsertTxError<P>"],["impl<P: Debug> Error for UpdateError<P>"],["impl<P: Debug> Error for UnresolvableConflict<P>"],["impl<P: Debug> Error for InsertTxError<P>"],["impl Error for InsertCheckpointError"],["impl<P: Debug> Error for UpdateError<P>"]], +"bdk_coin_select":[["impl Error for SelectionError"]], +"bdk_file_store":[["impl Error for FileError"],["impl Error for IterError"]], +"bdk_tmp_plan":[["impl Error for SigningError"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js index 655ad24360..4661e89a13 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js @@ -1,3 +1,10 @@ (function() {var implementors = { -"bdk":[["impl Debug for Error"],["impl Debug for AnyBlockchainConfig"],["impl Debug for ElectrumBlockchainConfig"],["impl Debug for RpcBlockchain"],["impl Debug for RpcConfig"],["impl Debug for RpcSyncParams"],["impl Debug for Auth"],["impl Debug for RpcBlockchainFactory"],["impl Debug for EsploraBlockchain"],["impl Debug for EsploraBlockchainConfig"],["impl Debug for Mempool"],["impl Debug for Peer"],["impl Debug for CompactFiltersBlockchain"],["impl Debug for BitcoinPeerConfig"],["impl Debug for CompactFiltersBlockchainConfig"],["impl Debug for CompactFiltersError"],["impl Debug for Capability"],["impl Debug for NoopProgress"],["impl Debug for LogProgress"],["impl Debug for AnyDatabase"],["impl Debug for SledDbConfiguration"],["impl Debug for SqliteDbConfiguration"],["impl Debug for AnyDatabaseConfig"],["impl Debug for SqliteDatabase"],["impl Debug for MemoryDatabase"],["impl Debug for SyncTime"],["impl Debug for Error"],["impl Debug for PkOrF"],["impl Debug for SatisfiableItem"],["impl Debug for Satisfaction"],["impl Debug for Policy"],["impl Debug for Condition"],["impl Debug for PolicyError"],["impl<'a> Debug for BuildSatisfaction<'a>"],["impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>"],["impl Debug for ScriptContextEnum"],["impl Debug for PrivateKeyGenerateOptions"],["impl Debug for KeyError"],["impl Debug for KeychainKind"],["impl Debug for FeeRate"],["impl Debug for LocalUtxo"],["impl Debug for WeightedUtxo"],["impl Debug for Utxo"],["impl Debug for TransactionDetails"],["impl Debug for BlockTime"],["impl Debug for Balance"],["impl Debug for Excess"],["impl Debug for CoinSelectionResult"],["impl Debug for LargestFirstCoinSelection"],["impl Debug for OldestFirstCoinSelection"],["impl Debug for BranchAndBoundCoinSelection"],["impl Debug for FullyNodedExport"],["impl Debug for SignerId"],["impl Debug for SignerError"],["impl Debug for SignerContext"],["impl<S: Debug + Sized + Debug + Clone> Debug for SignerWrapper<S>"],["impl Debug for SignerOrdering"],["impl Debug for SignersContainer"],["impl Debug for SignOptions"],["impl Debug for TapLeavesOptions"],["impl Debug for CreateTx"],["impl Debug for BumpFee"],["impl<'a, D: Debug, Cs: Debug, Ctx: Debug> Debug for TxBuilder<'a, D, Cs, Ctx>"],["impl Debug for TxOrdering"],["impl Debug for ChangeSpendPolicy"],["impl Debug for VerifyError"],["impl Debug for HWISigner"],["impl<D: Debug> Debug for Wallet<D>"],["impl Debug for AddressIndex"],["impl Debug for AddressInfo"],["impl Debug for SyncOptions"]] +"bdk":[["impl Debug for Error"],["impl Debug for Error"],["impl Debug for PkOrF"],["impl Debug for SatisfiableItem"],["impl Debug for Satisfaction"],["impl Debug for Policy"],["impl Debug for Condition"],["impl Debug for PolicyError"],["impl<'a> Debug for BuildSatisfaction<'a>"],["impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>"],["impl Debug for ScriptContextEnum"],["impl Debug for PrivateKeyGenerateOptions"],["impl Debug for KeyError"],["impl Debug for KeychainKind"],["impl Debug for FeeRate"],["impl Debug for LocalUtxo"],["impl Debug for WeightedUtxo"],["impl Debug for Utxo"],["impl Debug for TransactionDetails"],["impl Debug for Excess"],["impl Debug for CoinSelectionResult"],["impl Debug for LargestFirstCoinSelection"],["impl Debug for OldestFirstCoinSelection"],["impl Debug for BranchAndBoundCoinSelection"],["impl Debug for FullyNodedExport"],["impl Debug for SignerId"],["impl Debug for SignerError"],["impl Debug for SignerContext"],["impl<S: Debug + Sized + Debug + Clone> Debug for SignerWrapper<S>"],["impl Debug for SignerOrdering"],["impl Debug for SignersContainer"],["impl Debug for SignOptions"],["impl Debug for TapLeavesOptions"],["impl Debug for CreateTx"],["impl Debug for BumpFee"],["impl<'a, D: Debug, Cs: Debug, Ctx: Debug> Debug for TxBuilder<'a, D, Cs, Ctx>"],["impl Debug for TxOrdering"],["impl Debug for ChangeSpendPolicy"],["impl<D: Debug> Debug for Wallet<D>"],["impl Debug for AddressIndex"],["impl Debug for AddressInfo"],["impl<P: Debug> Debug for NewError<P>"]], +"bdk_chain":[["impl<P: Debug> Debug for ChainGraph<P>"],["impl<P: Debug> Debug for ChangeSet<P>"],["impl<P: Debug> Debug for NewError<P>"],["impl<P: Debug> Debug for InsertTxError<P>"],["impl<P: Debug> Debug for UpdateError<P>"],["impl<P: Debug> Debug for UnresolvableConflict<P>"],["impl<I: Debug> Debug for SpkTxOutIndex<I>"],["impl Debug for TxHeight"],["impl Debug for ConfirmationTime"],["impl Debug for BlockId"],["impl<I: Debug> Debug for FullTxOut<I>"],["impl<K: Debug, P: Debug, B: Debug> Debug for Persist<K, P, B>"],["impl<K: Debug, P: Debug> Debug for KeychainTracker<K, P>"],["impl<K: Debug> Debug for KeychainTxOutIndex<K>"],["impl<K: Debug> Debug for DerivationAdditions<K>"],["impl<K: Debug, P: Debug> Debug for KeychainScan<K, P>"],["impl<K: Debug, P: Debug> Debug for KeychainChangeSet<K, P>"],["impl Debug for Balance"],["impl<P: Debug> Debug for SparseChain<P>"],["impl<P: Debug> Debug for InsertTxError<P>"],["impl Debug for InsertCheckpointError"],["impl<P: Debug> Debug for UpdateError<P>"],["impl<P: Debug> Debug for ChangeSet<P>"],["impl Debug for TxGraph"],["impl Debug for Additions"]], +"bdk_coin_select":[["impl Debug for WeightedValue"],["impl Debug for CoinSelectorOpt"],["impl<'a> Debug for CoinSelector<'a>"],["impl Debug for SelectionError"],["impl Debug for SelectionConstraint"],["impl Debug for Selection"],["impl Debug for ExcessStrategyKind"],["impl Debug for ExcessStrategy"]], +"bdk_file_store":[["impl<K: Debug, P: Debug> Debug for KeychainStore<K, P>"],["impl Debug for FileError"],["impl Debug for IterError"]], +"bdk_tmp_plan":[["impl<Ak: Debug> Debug for Requirements<Ak>"],["impl<Ak: Debug> Debug for RequiredSignatures<Ak>"],["impl Debug for SigningError"],["impl<Ak: Debug> Debug for PlanKey<Ak>"],["impl<AK: Debug> Debug for Plan<AK>"],["impl Debug for SatisfactionMaterial"],["impl<K: Debug> Debug for Assets<K>"]], +"keychain_tracker_electrum_example":[["impl Debug for ElectrumCommands"],["impl Debug for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl Debug for EsploraCommands"],["impl Debug for ScanOptions"]], +"keychain_tracker_example_cli":[["impl<C: Debug + Subcommand> Debug for Commands<C>"],["impl Debug for CoinSelectionAlgo"],["impl Debug for AddressCmd"],["impl Debug for TxOutCmd"],["impl Debug for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js index a53371ee26..63778fe478 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js @@ -1,3 +1,8 @@ (function() {var implementors = { -"bdk":[["impl Display for Error"],["impl Display for CompactFiltersError"],["impl Display for Error"],["impl Display for PolicyError"],["impl Display for KeyError"],["impl Display for Balance"],["impl Display for SignerError"],["impl Display for VerifyError"],["impl Display for AddressInfo"]] +"bdk":[["impl Display for Error"],["impl Display for Error"],["impl Display for PolicyError"],["impl Display for KeyError"],["impl Display for SignerError"],["impl Display for AddressInfo"],["impl<P> Display for NewError<P>where
        P: Display,
    "]], +"bdk_chain":[["impl<P: Debug> Display for NewError<P>"],["impl<P: Debug> Display for InsertTxError<P>"],["impl<P: Debug> Display for UpdateError<P>"],["impl<P: Debug> Display for UnresolvableConflict<P>"],["impl Display for TxHeight"],["impl Display for Balance"],["impl<P: Debug> Display for InsertTxError<P>"],["impl Display for InsertCheckpointError"],["impl<P: Debug> Display for UpdateError<P>"]], +"bdk_coin_select":[["impl Display for SelectionError"],["impl Display for SelectionConstraint"],["impl Display for ExcessStrategyKind"]], +"bdk_file_store":[["impl Display for FileError"],["impl Display for IterError"]], +"bdk_tmp_plan":[["impl Display for SigningError"]], +"keychain_tracker_example_cli":[["impl Display for CoinSelectionAlgo"],["impl Display for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js index 5777e71c6f..c7d299a200 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js @@ -1,3 +1,5 @@ (function() {var implementors = { -"bdk":[["impl Hash for Auth"],["impl Hash for Capability"],["impl Hash for PkOrF"],["impl Hash for Condition"],["impl Hash for KeychainKind"],["impl Hash for LocalUtxo"],["impl Hash for SignerId"],["impl Hash for TxOrdering"],["impl Hash for ChangeSpendPolicy"]] +"bdk":[["impl Hash for PkOrF"],["impl Hash for Condition"],["impl Hash for KeychainKind"],["impl Hash for LocalUtxo"],["impl Hash for SignerId"],["impl Hash for TxOrdering"],["impl Hash for ChangeSpendPolicy"]], +"bdk_chain":[["impl Hash for TxHeight"],["impl Hash for ConfirmationTime"]], +"bdk_coin_select":[["impl Hash for ExcessStrategyKind"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/iter/traits/accum/trait.Sum.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/iter/traits/accum/trait.Sum.js deleted file mode 100644 index b140d668cc..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/iter/traits/accum/trait.Sum.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = { -"bdk":[["impl Sum<Balance> for Balance"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/iter/traits/iterator/trait.Iterator.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/iter/traits/iterator/trait.Iterator.js new file mode 100644 index 0000000000..ea6bf7ce16 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/iter/traits/iterator/trait.Iterator.js @@ -0,0 +1,5 @@ +(function() {var implementors = { +"bdk_chain":[["impl<'g, F, O> Iterator for TxDescendants<'g, F>where
        F: FnMut(usize, Txid) -> Option<O>,
    "]], +"bdk_coin_select":[["impl<'c, 'f, S: Ord + Copy + Display> Iterator for BnbIter<'c, 'f, S>"]], +"bdk_file_store":[["impl<'a, V> Iterator for EntryIter<'a, V>where
        V: DeserializeOwned,
    "]] +};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js index 0226f2c234..b6e1c862ef 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js @@ -1,3 +1,6 @@ (function() {var implementors = { -"bdk":[["impl Copy for Capability"],["impl Copy for NoopProgress"],["impl Copy for LogProgress"],["impl Copy for Condition"],["impl<'a> Copy for BuildSatisfaction<'a>"],["impl Copy for ScriptContextEnum"],["impl Copy for PrivateKeyGenerateOptions"],["impl Copy for KeychainKind"],["impl Copy for FeeRate"],["impl Copy for LargestFirstCoinSelection"],["impl Copy for OldestFirstCoinSelection"],["impl Copy for SignerContext"],["impl Copy for TxOrdering"],["impl Copy for ChangeSpendPolicy"]] +"bdk":[["impl Copy for Condition"],["impl<'a> Copy for BuildSatisfaction<'a>"],["impl Copy for ScriptContextEnum"],["impl Copy for PrivateKeyGenerateOptions"],["impl Copy for KeychainKind"],["impl Copy for FeeRate"],["impl Copy for LargestFirstCoinSelection"],["impl Copy for OldestFirstCoinSelection"],["impl Copy for SignerContext"],["impl Copy for TxOrdering"],["impl Copy for ChangeSpendPolicy"]], +"bdk_chain":[["impl Copy for TxHeight"],["impl Copy for ConfirmationTime"],["impl Copy for BlockId"]], +"bdk_coin_select":[["impl Copy for WeightedValue"],["impl Copy for CoinSelectorOpt"],["impl Copy for SelectionConstraint"],["impl Copy for ExcessStrategyKind"],["impl Copy for ExcessStrategy"]], +"keychain_tracker_example_cli":[["impl Copy for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js index 83946b5b28..e59134cc76 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js @@ -1,3 +1,11 @@ (function() {var implementors = { -"bdk":[["impl Freeze for Error",1,["bdk::error::Error"]],["impl Freeze for AnyBlockchain",1,["bdk::blockchain::any::AnyBlockchain"]],["impl Freeze for AnyBlockchainConfig",1,["bdk::blockchain::any::AnyBlockchainConfig"]],["impl !Freeze for ElectrumBlockchain",1,["bdk::blockchain::electrum::ElectrumBlockchain"]],["impl Freeze for ElectrumBlockchainConfig",1,["bdk::blockchain::electrum::ElectrumBlockchainConfig"]],["impl !Freeze for RpcBlockchain",1,["bdk::blockchain::rpc::RpcBlockchain"]],["impl Freeze for RpcConfig",1,["bdk::blockchain::rpc::RpcConfig"]],["impl Freeze for RpcSyncParams",1,["bdk::blockchain::rpc::RpcSyncParams"]],["impl Freeze for Auth",1,["bdk::blockchain::rpc::Auth"]],["impl Freeze for RpcBlockchainFactory",1,["bdk::blockchain::rpc::RpcBlockchainFactory"]],["impl Freeze for EsploraBlockchain",1,["bdk::blockchain::esplora::blocking::EsploraBlockchain"]],["impl Freeze for EsploraBlockchainConfig",1,["bdk::blockchain::esplora::EsploraBlockchainConfig"]],["impl !Freeze for Mempool",1,["bdk::blockchain::compact_filters::peer::Mempool"]],["impl Freeze for Peer",1,["bdk::blockchain::compact_filters::peer::Peer"]],["impl Freeze for CompactFiltersBlockchain",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]],["impl Freeze for BitcoinPeerConfig",1,["bdk::blockchain::compact_filters::BitcoinPeerConfig"]],["impl Freeze for CompactFiltersBlockchainConfig",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]],["impl Freeze for CompactFiltersError",1,["bdk::blockchain::compact_filters::CompactFiltersError"]],["impl Freeze for Capability",1,["bdk::blockchain::Capability"]],["impl Freeze for NoopProgress",1,["bdk::blockchain::NoopProgress"]],["impl Freeze for LogProgress",1,["bdk::blockchain::LogProgress"]],["impl !Freeze for AnyDatabase",1,["bdk::database::any::AnyDatabase"]],["impl !Freeze for AnyBatch",1,["bdk::database::any::AnyBatch"]],["impl Freeze for SledDbConfiguration",1,["bdk::database::any::SledDbConfiguration"]],["impl Freeze for SqliteDbConfiguration",1,["bdk::database::any::SqliteDbConfiguration"]],["impl Freeze for AnyDatabaseConfig",1,["bdk::database::any::AnyDatabaseConfig"]],["impl !Freeze for SqliteDatabase",1,["bdk::database::sqlite::SqliteDatabase"]],["impl Freeze for MemoryDatabase",1,["bdk::database::memory::MemoryDatabase"]],["impl Freeze for SyncTime",1,["bdk::database::SyncTime"]],["impl Freeze for Error",1,["bdk::descriptor::error::Error"]],["impl Freeze for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Freeze for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Freeze for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Freeze for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Freeze for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Freeze for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Freeze for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Freeze for P2Pkh<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Freeze for P2Wpkh_P2Sh<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Freeze for P2Wpkh<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Freeze for Bip44<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Freeze for Bip44Public<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Freeze for Bip49<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Freeze for Bip49Public<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Freeze for Bip84<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Freeze for Bip84Public<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl Freeze for WordCount",1,["bdk::keys::bip39::WordCount"]],["impl<Ctx> Freeze for DescriptorKey<Ctx>",1,["bdk::keys::DescriptorKey"]],["impl Freeze for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Freeze for ExtendedKey<Ctx>",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Freeze for GeneratedKey<K, Ctx>where
        K: Freeze,
    ",1,["bdk::keys::GeneratedKey"]],["impl Freeze for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Freeze for KeyError",1,["bdk::keys::KeyError"]],["impl Freeze for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Freeze for FeeRate",1,["bdk::types::FeeRate"]],["impl Freeze for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Freeze for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Freeze for Utxo",1,["bdk::types::Utxo"]],["impl Freeze for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Freeze for BlockTime",1,["bdk::types::BlockTime"]],["impl Freeze for Balance",1,["bdk::types::Balance"]],["impl Freeze for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Freeze for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Freeze for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Freeze for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Freeze for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Freeze for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Freeze for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Freeze for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Freeze for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Freeze for SignerWrapper<S>where
        S: Freeze,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Freeze for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Freeze for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Freeze for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Freeze for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Freeze for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Freeze for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> Freeze for TxBuilder<'a, D, Cs, Ctx>where
        Cs: Freeze,
    ",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Freeze for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Freeze for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Freeze for VerifyError",1,["bdk::wallet::verify::VerifyError"]],["impl Freeze for HWISigner",1,["bdk::wallet::hardwaresigner::HWISigner"]],["impl<D> !Freeze for Wallet<D>",1,["bdk::wallet::Wallet"]],["impl Freeze for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Freeze for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl Freeze for SyncOptions",1,["bdk::wallet::SyncOptions"]]] +"bdk":[["impl Freeze for Error",1,["bdk::error::Error"]],["impl Freeze for Error",1,["bdk::descriptor::error::Error"]],["impl Freeze for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Freeze for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Freeze for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Freeze for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Freeze for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Freeze for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Freeze for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Freeze for P2Pkh<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Freeze for P2Wpkh_P2Sh<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Freeze for P2Wpkh<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Freeze for Bip44<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Freeze for Bip44Public<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Freeze for Bip49<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Freeze for Bip49Public<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Freeze for Bip84<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Freeze for Bip84Public<K>where
        K: Freeze,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl<Ctx> Freeze for DescriptorKey<Ctx>",1,["bdk::keys::DescriptorKey"]],["impl Freeze for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Freeze for ExtendedKey<Ctx>",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Freeze for GeneratedKey<K, Ctx>where
        K: Freeze,
    ",1,["bdk::keys::GeneratedKey"]],["impl Freeze for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Freeze for KeyError",1,["bdk::keys::KeyError"]],["impl Freeze for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Freeze for FeeRate",1,["bdk::types::FeeRate"]],["impl Freeze for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Freeze for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Freeze for Utxo",1,["bdk::types::Utxo"]],["impl Freeze for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Freeze for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Freeze for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Freeze for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Freeze for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Freeze for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Freeze for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Freeze for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Freeze for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Freeze for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Freeze for SignerWrapper<S>where
        S: Freeze,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Freeze for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Freeze for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Freeze for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Freeze for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Freeze for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Freeze for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> Freeze for TxBuilder<'a, D, Cs, Ctx>where
        Cs: Freeze,
    ",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Freeze for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Freeze for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl<D> Freeze for Wallet<D>where
        D: Freeze,
    ",1,["bdk::wallet::Wallet"]],["impl Freeze for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Freeze for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl<P> Freeze for NewError<P>where
        P: Freeze,
    ",1,["bdk::wallet::NewError"]]], +"bdk_chain":[["impl<P> Freeze for ChainGraph<P>",1,["bdk_chain::chain_graph::ChainGraph"]],["impl<P> Freeze for ChangeSet<P>",1,["bdk_chain::chain_graph::ChangeSet"]],["impl<P> Freeze for NewError<P>where
        P: Freeze,
    ",1,["bdk_chain::chain_graph::NewError"]],["impl<P> Freeze for InsertTxError<P>where
        P: Freeze,
    ",1,["bdk_chain::chain_graph::InsertTxError"]],["impl<P> Freeze for UpdateError<P>where
        P: Freeze,
    ",1,["bdk_chain::chain_graph::UpdateError"]],["impl<P> Freeze for UnresolvableConflict<P>where
        P: Freeze,
    ",1,["bdk_chain::chain_graph::UnresolvableConflict"]],["impl<I> Freeze for SpkTxOutIndex<I>",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl Freeze for TxHeight",1,["bdk_chain::chain_data::TxHeight"]],["impl Freeze for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Freeze for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl<I> Freeze for FullTxOut<I>where
        I: Freeze,
    ",1,["bdk_chain::chain_data::FullTxOut"]],["impl<K, P, B> Freeze for Persist<K, P, B>where
        B: Freeze,
    ",1,["bdk_chain::keychain::persist::Persist"]],["impl<K, P> Freeze for KeychainTracker<K, P>",1,["bdk_chain::keychain::tracker::KeychainTracker"]],["impl<K> Freeze for KeychainTxOutIndex<K>",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl<K> Freeze for DerivationAdditions<K>",1,["bdk_chain::keychain::DerivationAdditions"]],["impl<K, P> Freeze for KeychainScan<K, P>",1,["bdk_chain::keychain::KeychainScan"]],["impl<K, P> Freeze for KeychainChangeSet<K, P>",1,["bdk_chain::keychain::KeychainChangeSet"]],["impl Freeze for Balance",1,["bdk_chain::keychain::Balance"]],["impl<P> Freeze for SparseChain<P>",1,["bdk_chain::sparse_chain::SparseChain"]],["impl<P> Freeze for InsertTxError<P>where
        P: Freeze,
    ",1,["bdk_chain::sparse_chain::InsertTxError"]],["impl Freeze for InsertCheckpointError",1,["bdk_chain::sparse_chain::InsertCheckpointError"]],["impl<P> Freeze for UpdateError<P>where
        P: Freeze,
    ",1,["bdk_chain::sparse_chain::UpdateError"]],["impl<P> Freeze for ChangeSet<P>",1,["bdk_chain::sparse_chain::ChangeSet"]],["impl Freeze for TxGraph",1,["bdk_chain::tx_graph::TxGraph"]],["impl Freeze for Additions",1,["bdk_chain::tx_graph::Additions"]],["impl<'g, F> Freeze for TxDescendants<'g, F>where
        F: Freeze,
    ",1,["bdk_chain::tx_graph::TxDescendants"]]], +"bdk_coin_select":[["impl Freeze for WeightedValue",1,["bdk_coin_select::coin_selector::WeightedValue"]],["impl Freeze for CoinSelectorOpt",1,["bdk_coin_select::coin_selector::CoinSelectorOpt"]],["impl<'a> Freeze for CoinSelector<'a>",1,["bdk_coin_select::coin_selector::CoinSelector"]],["impl Freeze for SelectionError",1,["bdk_coin_select::coin_selector::SelectionError"]],["impl Freeze for SelectionConstraint",1,["bdk_coin_select::coin_selector::SelectionConstraint"]],["impl Freeze for Selection",1,["bdk_coin_select::coin_selector::Selection"]],["impl Freeze for ExcessStrategyKind",1,["bdk_coin_select::coin_selector::ExcessStrategyKind"]],["impl Freeze for ExcessStrategy",1,["bdk_coin_select::coin_selector::ExcessStrategy"]],["impl Freeze for BranchStrategy",1,["bdk_coin_select::bnb::BranchStrategy"]],["impl<'c, S> Freeze for Bnb<'c, S>where
        S: Freeze,
    ",1,["bdk_coin_select::bnb::Bnb"]],["impl<'c, 'f, S> Freeze for BnbIter<'c, 'f, S>where
        S: Freeze,
    ",1,["bdk_coin_select::bnb::BnbIter"]],["impl Freeze for BnbLimit",1,["bdk_coin_select::bnb::BnbLimit"]]], +"bdk_electrum":[["impl<K, P> Freeze for ElectrumUpdate<K, P>",1,["bdk_electrum::ElectrumUpdate"]]], +"bdk_file_store":[["impl<K, P> Freeze for KeychainStore<K, P>",1,["bdk_file_store::file_store::KeychainStore"]],["impl Freeze for FileError",1,["bdk_file_store::file_store::FileError"]],["impl Freeze for IterError",1,["bdk_file_store::file_store::IterError"]],["impl<'a, V> Freeze for EntryIter<'a, V>",1,["bdk_file_store::file_store::EntryIter"]]], +"bdk_tmp_plan":[["impl<Ak> Freeze for Requirements<Ak>where
        Ak: Freeze,
    ",1,["bdk_tmp_plan::requirements::Requirements"]],["impl<Ak> Freeze for RequiredSignatures<Ak>where
        Ak: Freeze,
    ",1,["bdk_tmp_plan::requirements::RequiredSignatures"]],["impl Freeze for SigningError",1,["bdk_tmp_plan::requirements::SigningError"]],["impl<Ak> Freeze for PlanKey<Ak>where
        Ak: Freeze,
    ",1,["bdk_tmp_plan::template::PlanKey"]],["impl<AK> !Freeze for Plan<AK>",1,["bdk_tmp_plan::Plan"]],["impl Freeze for SatisfactionMaterial",1,["bdk_tmp_plan::SatisfactionMaterial"]],["impl<Ak> Freeze for PlanState<Ak>where
        Ak: Freeze,
    ",1,["bdk_tmp_plan::PlanState"]],["impl<K> Freeze for Assets<K>",1,["bdk_tmp_plan::Assets"]]], +"keychain_tracker_electrum_example":[["impl Freeze for ElectrumCommands",1,["keychain_tracker_electrum_example::ElectrumCommands"]],["impl Freeze for ScanOptions",1,["keychain_tracker_electrum_example::ScanOptions"]]], +"keychain_tracker_esplora_example":[["impl Freeze for EsploraCommands",1,["keychain_tracker_esplora_example::EsploraCommands"]],["impl Freeze for ScanOptions",1,["keychain_tracker_esplora_example::ScanOptions"]]], +"keychain_tracker_example_cli":[["impl<C> Freeze for Args<C>where
        C: Freeze,
    ",1,["keychain_tracker_example_cli::Args"]],["impl<C> Freeze for Commands<C>where
        C: Freeze,
    ",1,["keychain_tracker_example_cli::Commands"]],["impl Freeze for CoinSelectionAlgo",1,["keychain_tracker_example_cli::CoinSelectionAlgo"]],["impl Freeze for AddressCmd",1,["keychain_tracker_example_cli::AddressCmd"]],["impl Freeze for TxOutCmd",1,["keychain_tracker_example_cli::TxOutCmd"]],["impl Freeze for Keychain",1,["keychain_tracker_example_cli::Keychain"]],["impl Freeze for AddrsOutput",1,["keychain_tracker_example_cli::AddrsOutput"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js index 7c0843885b..fa6dd93999 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js @@ -1,3 +1,11 @@ (function() {var implementors = { -"bdk":[["impl Send for Error",1,["bdk::error::Error"]],["impl Send for AnyBlockchain",1,["bdk::blockchain::any::AnyBlockchain"]],["impl Send for AnyBlockchainConfig",1,["bdk::blockchain::any::AnyBlockchainConfig"]],["impl Send for ElectrumBlockchain",1,["bdk::blockchain::electrum::ElectrumBlockchain"]],["impl Send for ElectrumBlockchainConfig",1,["bdk::blockchain::electrum::ElectrumBlockchainConfig"]],["impl Send for RpcBlockchain",1,["bdk::blockchain::rpc::RpcBlockchain"]],["impl Send for RpcConfig",1,["bdk::blockchain::rpc::RpcConfig"]],["impl Send for RpcSyncParams",1,["bdk::blockchain::rpc::RpcSyncParams"]],["impl Send for Auth",1,["bdk::blockchain::rpc::Auth"]],["impl Send for RpcBlockchainFactory",1,["bdk::blockchain::rpc::RpcBlockchainFactory"]],["impl Send for EsploraBlockchain",1,["bdk::blockchain::esplora::blocking::EsploraBlockchain"]],["impl Send for EsploraBlockchainConfig",1,["bdk::blockchain::esplora::EsploraBlockchainConfig"]],["impl Send for Mempool",1,["bdk::blockchain::compact_filters::peer::Mempool"]],["impl Send for Peer",1,["bdk::blockchain::compact_filters::peer::Peer"]],["impl Send for CompactFiltersBlockchain",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]],["impl Send for BitcoinPeerConfig",1,["bdk::blockchain::compact_filters::BitcoinPeerConfig"]],["impl Send for CompactFiltersBlockchainConfig",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]],["impl Send for CompactFiltersError",1,["bdk::blockchain::compact_filters::CompactFiltersError"]],["impl Send for Capability",1,["bdk::blockchain::Capability"]],["impl Send for NoopProgress",1,["bdk::blockchain::NoopProgress"]],["impl Send for LogProgress",1,["bdk::blockchain::LogProgress"]],["impl Send for AnyDatabase",1,["bdk::database::any::AnyDatabase"]],["impl Send for AnyBatch",1,["bdk::database::any::AnyBatch"]],["impl Send for SledDbConfiguration",1,["bdk::database::any::SledDbConfiguration"]],["impl Send for SqliteDbConfiguration",1,["bdk::database::any::SqliteDbConfiguration"]],["impl Send for AnyDatabaseConfig",1,["bdk::database::any::AnyDatabaseConfig"]],["impl Send for SqliteDatabase",1,["bdk::database::sqlite::SqliteDatabase"]],["impl Send for MemoryDatabase",1,["bdk::database::memory::MemoryDatabase"]],["impl Send for SyncTime",1,["bdk::database::SyncTime"]],["impl Send for Error",1,["bdk::descriptor::error::Error"]],["impl Send for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Send for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Send for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Send for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Send for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Send for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Send for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Send for P2Pkh<K>where
        K: Send,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Send for P2Wpkh_P2Sh<K>where
        K: Send,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Send for P2Wpkh<K>where
        K: Send,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Send for Bip44<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Send for Bip44Public<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Send for Bip49<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Send for Bip49Public<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Send for Bip84<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Send for Bip84Public<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl Send for WordCount",1,["bdk::keys::bip39::WordCount"]],["impl<Ctx> Send for DescriptorKey<Ctx>where
        Ctx: Send,
    ",1,["bdk::keys::DescriptorKey"]],["impl Send for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Send for ExtendedKey<Ctx>where
        Ctx: Send,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Send for GeneratedKey<K, Ctx>where
        Ctx: Send,
        K: Send,
    ",1,["bdk::keys::GeneratedKey"]],["impl Send for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Send for KeyError",1,["bdk::keys::KeyError"]],["impl Send for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Send for FeeRate",1,["bdk::types::FeeRate"]],["impl Send for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Send for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Send for Utxo",1,["bdk::types::Utxo"]],["impl Send for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Send for BlockTime",1,["bdk::types::BlockTime"]],["impl Send for Balance",1,["bdk::types::Balance"]],["impl Send for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Send for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Send for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Send for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Send for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Send for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Send for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Send for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Send for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Send for SignerWrapper<S>where
        S: Send,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Send for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Send for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Send for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Send for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Send for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Send for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !Send for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Send for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Send for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Send for VerifyError",1,["bdk::wallet::verify::VerifyError"]],["impl Send for HWISigner",1,["bdk::wallet::hardwaresigner::HWISigner"]],["impl<D> Send for Wallet<D>where
        D: Send,
    ",1,["bdk::wallet::Wallet"]],["impl Send for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Send for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl Send for SyncOptions",1,["bdk::wallet::SyncOptions"]]] +"bdk":[["impl Send for Error",1,["bdk::error::Error"]],["impl Send for Error",1,["bdk::descriptor::error::Error"]],["impl Send for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Send for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Send for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Send for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Send for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Send for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Send for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Send for P2Pkh<K>where
        K: Send,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Send for P2Wpkh_P2Sh<K>where
        K: Send,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Send for P2Wpkh<K>where
        K: Send,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Send for Bip44<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Send for Bip44Public<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Send for Bip49<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Send for Bip49Public<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Send for Bip84<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Send for Bip84Public<K>where
        K: Send,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl<Ctx> Send for DescriptorKey<Ctx>where
        Ctx: Send,
    ",1,["bdk::keys::DescriptorKey"]],["impl Send for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Send for ExtendedKey<Ctx>where
        Ctx: Send,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Send for GeneratedKey<K, Ctx>where
        Ctx: Send,
        K: Send,
    ",1,["bdk::keys::GeneratedKey"]],["impl Send for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Send for KeyError",1,["bdk::keys::KeyError"]],["impl Send for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Send for FeeRate",1,["bdk::types::FeeRate"]],["impl Send for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Send for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Send for Utxo",1,["bdk::types::Utxo"]],["impl Send for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Send for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Send for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Send for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Send for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Send for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Send for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Send for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Send for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Send for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Send for SignerWrapper<S>where
        S: Send,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Send for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Send for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Send for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Send for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Send for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Send for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !Send for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Send for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Send for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl<D> Send for Wallet<D>where
        D: Send,
    ",1,["bdk::wallet::Wallet"]],["impl Send for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Send for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl<P> Send for NewError<P>where
        P: Send,
    ",1,["bdk::wallet::NewError"]]], +"bdk_chain":[["impl<P> Send for ChainGraph<P>where
        P: Send,
    ",1,["bdk_chain::chain_graph::ChainGraph"]],["impl<P> Send for ChangeSet<P>where
        P: Send,
    ",1,["bdk_chain::chain_graph::ChangeSet"]],["impl<P> Send for NewError<P>where
        P: Send,
    ",1,["bdk_chain::chain_graph::NewError"]],["impl<P> Send for InsertTxError<P>where
        P: Send,
    ",1,["bdk_chain::chain_graph::InsertTxError"]],["impl<P> Send for UpdateError<P>where
        P: Send,
    ",1,["bdk_chain::chain_graph::UpdateError"]],["impl<P> Send for UnresolvableConflict<P>where
        P: Send,
    ",1,["bdk_chain::chain_graph::UnresolvableConflict"]],["impl<I> Send for SpkTxOutIndex<I>where
        I: Send,
    ",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl Send for TxHeight",1,["bdk_chain::chain_data::TxHeight"]],["impl Send for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Send for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl<I> Send for FullTxOut<I>where
        I: Send,
    ",1,["bdk_chain::chain_data::FullTxOut"]],["impl<K, P, B> Send for Persist<K, P, B>where
        B: Send,
        K: Send,
        P: Send,
    ",1,["bdk_chain::keychain::persist::Persist"]],["impl<K, P> Send for KeychainTracker<K, P>where
        K: Send,
        P: Send,
    ",1,["bdk_chain::keychain::tracker::KeychainTracker"]],["impl<K> Send for KeychainTxOutIndex<K>where
        K: Send,
    ",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl<K> Send for DerivationAdditions<K>where
        K: Send,
    ",1,["bdk_chain::keychain::DerivationAdditions"]],["impl<K, P> Send for KeychainScan<K, P>where
        K: Send,
        P: Send,
    ",1,["bdk_chain::keychain::KeychainScan"]],["impl<K, P> Send for KeychainChangeSet<K, P>where
        K: Send,
        P: Send,
    ",1,["bdk_chain::keychain::KeychainChangeSet"]],["impl Send for Balance",1,["bdk_chain::keychain::Balance"]],["impl<P> Send for SparseChain<P>where
        P: Send,
    ",1,["bdk_chain::sparse_chain::SparseChain"]],["impl<P> Send for InsertTxError<P>where
        P: Send,
    ",1,["bdk_chain::sparse_chain::InsertTxError"]],["impl Send for InsertCheckpointError",1,["bdk_chain::sparse_chain::InsertCheckpointError"]],["impl<P> Send for UpdateError<P>where
        P: Send,
    ",1,["bdk_chain::sparse_chain::UpdateError"]],["impl<P> Send for ChangeSet<P>where
        P: Send,
    ",1,["bdk_chain::sparse_chain::ChangeSet"]],["impl Send for TxGraph",1,["bdk_chain::tx_graph::TxGraph"]],["impl Send for Additions",1,["bdk_chain::tx_graph::Additions"]],["impl<'g, F> Send for TxDescendants<'g, F>where
        F: Send,
    ",1,["bdk_chain::tx_graph::TxDescendants"]]], +"bdk_coin_select":[["impl Send for WeightedValue",1,["bdk_coin_select::coin_selector::WeightedValue"]],["impl Send for CoinSelectorOpt",1,["bdk_coin_select::coin_selector::CoinSelectorOpt"]],["impl<'a> Send for CoinSelector<'a>",1,["bdk_coin_select::coin_selector::CoinSelector"]],["impl Send for SelectionError",1,["bdk_coin_select::coin_selector::SelectionError"]],["impl Send for SelectionConstraint",1,["bdk_coin_select::coin_selector::SelectionConstraint"]],["impl Send for Selection",1,["bdk_coin_select::coin_selector::Selection"]],["impl Send for ExcessStrategyKind",1,["bdk_coin_select::coin_selector::ExcessStrategyKind"]],["impl Send for ExcessStrategy",1,["bdk_coin_select::coin_selector::ExcessStrategy"]],["impl Send for BranchStrategy",1,["bdk_coin_select::bnb::BranchStrategy"]],["impl<'c, S> Send for Bnb<'c, S>where
        S: Send,
    ",1,["bdk_coin_select::bnb::Bnb"]],["impl<'c, 'f, S> !Send for BnbIter<'c, 'f, S>",1,["bdk_coin_select::bnb::BnbIter"]],["impl Send for BnbLimit",1,["bdk_coin_select::bnb::BnbLimit"]]], +"bdk_electrum":[["impl<K, P> Send for ElectrumUpdate<K, P>where
        K: Send,
        P: Send,
    ",1,["bdk_electrum::ElectrumUpdate"]]], +"bdk_file_store":[["impl<K, P> Send for KeychainStore<K, P>where
        K: Send,
        P: Send,
    ",1,["bdk_file_store::file_store::KeychainStore"]],["impl Send for FileError",1,["bdk_file_store::file_store::FileError"]],["impl Send for IterError",1,["bdk_file_store::file_store::IterError"]],["impl<'a, V> Send for EntryIter<'a, V>where
        V: Send,
    ",1,["bdk_file_store::file_store::EntryIter"]]], +"bdk_tmp_plan":[["impl<Ak> Send for Requirements<Ak>where
        Ak: Send,
    ",1,["bdk_tmp_plan::requirements::Requirements"]],["impl<Ak> Send for RequiredSignatures<Ak>where
        Ak: Send,
    ",1,["bdk_tmp_plan::requirements::RequiredSignatures"]],["impl Send for SigningError",1,["bdk_tmp_plan::requirements::SigningError"]],["impl<Ak> Send for PlanKey<Ak>where
        Ak: Send,
    ",1,["bdk_tmp_plan::template::PlanKey"]],["impl<AK> Send for Plan<AK>where
        AK: Send,
    ",1,["bdk_tmp_plan::Plan"]],["impl Send for SatisfactionMaterial",1,["bdk_tmp_plan::SatisfactionMaterial"]],["impl<Ak> Send for PlanState<Ak>where
        Ak: Send,
    ",1,["bdk_tmp_plan::PlanState"]],["impl<K> Send for Assets<K>where
        K: Send,
    ",1,["bdk_tmp_plan::Assets"]]], +"keychain_tracker_electrum_example":[["impl Send for ElectrumCommands",1,["keychain_tracker_electrum_example::ElectrumCommands"]],["impl Send for ScanOptions",1,["keychain_tracker_electrum_example::ScanOptions"]]], +"keychain_tracker_esplora_example":[["impl Send for EsploraCommands",1,["keychain_tracker_esplora_example::EsploraCommands"]],["impl Send for ScanOptions",1,["keychain_tracker_esplora_example::ScanOptions"]]], +"keychain_tracker_example_cli":[["impl<C> Send for Args<C>where
        C: Send,
    ",1,["keychain_tracker_example_cli::Args"]],["impl<C> Send for Commands<C>where
        C: Send,
    ",1,["keychain_tracker_example_cli::Commands"]],["impl Send for CoinSelectionAlgo",1,["keychain_tracker_example_cli::CoinSelectionAlgo"]],["impl Send for AddressCmd",1,["keychain_tracker_example_cli::AddressCmd"]],["impl Send for TxOutCmd",1,["keychain_tracker_example_cli::TxOutCmd"]],["impl Send for Keychain",1,["keychain_tracker_example_cli::Keychain"]],["impl Send for AddrsOutput",1,["keychain_tracker_example_cli::AddrsOutput"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js index ada9c612ad..54de3d13b6 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js @@ -1,3 +1,6 @@ (function() {var implementors = { -"bdk":[["impl StructuralEq for AnyBlockchainConfig"],["impl StructuralEq for ElectrumBlockchainConfig"],["impl StructuralEq for RpcConfig"],["impl StructuralEq for RpcSyncParams"],["impl StructuralEq for Auth"],["impl StructuralEq for EsploraBlockchainConfig"],["impl StructuralEq for BitcoinPeerConfig"],["impl StructuralEq for CompactFiltersBlockchainConfig"],["impl StructuralEq for Capability"],["impl StructuralEq for SyncTime"],["impl StructuralEq for PkOrF"],["impl StructuralEq for SatisfiableItem"],["impl StructuralEq for Satisfaction"],["impl StructuralEq for Policy"],["impl StructuralEq for Condition"],["impl StructuralEq for PolicyError"],["impl StructuralEq for ScriptContextEnum"],["impl StructuralEq for KeychainKind"],["impl StructuralEq for LocalUtxo"],["impl StructuralEq for WeightedUtxo"],["impl StructuralEq for Utxo"],["impl StructuralEq for TransactionDetails"],["impl StructuralEq for BlockTime"],["impl StructuralEq for Balance"],["impl StructuralEq for SignerId"],["impl StructuralEq for SignerError"],["impl StructuralEq for SignerContext"],["impl StructuralEq for SignerOrdering"],["impl StructuralEq for TapLeavesOptions"],["impl StructuralEq for TxOrdering"],["impl StructuralEq for ChangeSpendPolicy"],["impl StructuralEq for AddressInfo"]] +"bdk":[["impl StructuralEq for PkOrF"],["impl StructuralEq for SatisfiableItem"],["impl StructuralEq for Satisfaction"],["impl StructuralEq for Policy"],["impl StructuralEq for Condition"],["impl StructuralEq for PolicyError"],["impl StructuralEq for ScriptContextEnum"],["impl StructuralEq for KeychainKind"],["impl StructuralEq for LocalUtxo"],["impl StructuralEq for WeightedUtxo"],["impl StructuralEq for Utxo"],["impl StructuralEq for TransactionDetails"],["impl StructuralEq for SignerId"],["impl StructuralEq for SignerError"],["impl StructuralEq for SignerContext"],["impl StructuralEq for SignerOrdering"],["impl StructuralEq for TapLeavesOptions"],["impl StructuralEq for TxOrdering"],["impl StructuralEq for ChangeSpendPolicy"],["impl StructuralEq for AddressInfo"]], +"bdk_chain":[["impl StructuralEq for TxHeight"],["impl StructuralEq for ConfirmationTime"],["impl StructuralEq for BlockId"],["impl StructuralEq for Balance"]], +"bdk_coin_select":[["impl StructuralEq for SelectionConstraint"],["impl StructuralEq for ExcessStrategyKind"]], +"keychain_tracker_example_cli":[["impl StructuralEq for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js index f4d767e86e..dcc9f07dbe 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js @@ -1,3 +1,8 @@ (function() {var implementors = { -"bdk":[["impl StructuralPartialEq for AnyBlockchainConfig"],["impl StructuralPartialEq for ElectrumBlockchainConfig"],["impl StructuralPartialEq for RpcConfig"],["impl StructuralPartialEq for RpcSyncParams"],["impl StructuralPartialEq for Auth"],["impl StructuralPartialEq for EsploraBlockchainConfig"],["impl StructuralPartialEq for BitcoinPeerConfig"],["impl StructuralPartialEq for CompactFiltersBlockchainConfig"],["impl StructuralPartialEq for Capability"],["impl StructuralPartialEq for SyncTime"],["impl StructuralPartialEq for PkOrF"],["impl StructuralPartialEq for SatisfiableItem"],["impl StructuralPartialEq for Satisfaction"],["impl StructuralPartialEq for Policy"],["impl StructuralPartialEq for Condition"],["impl StructuralPartialEq for PolicyError"],["impl StructuralPartialEq for ScriptContextEnum"],["impl StructuralPartialEq for KeychainKind"],["impl StructuralPartialEq for FeeRate"],["impl StructuralPartialEq for LocalUtxo"],["impl StructuralPartialEq for WeightedUtxo"],["impl StructuralPartialEq for Utxo"],["impl StructuralPartialEq for TransactionDetails"],["impl StructuralPartialEq for BlockTime"],["impl StructuralPartialEq for Balance"],["impl StructuralPartialEq for SignerId"],["impl StructuralPartialEq for SignerError"],["impl StructuralPartialEq for SignerContext"],["impl StructuralPartialEq for SignerOrdering"],["impl StructuralPartialEq for TapLeavesOptions"],["impl StructuralPartialEq for TxOrdering"],["impl StructuralPartialEq for ChangeSpendPolicy"],["impl StructuralPartialEq for AddressInfo"]] +"bdk":[["impl StructuralPartialEq for PkOrF"],["impl StructuralPartialEq for SatisfiableItem"],["impl StructuralPartialEq for Satisfaction"],["impl StructuralPartialEq for Policy"],["impl StructuralPartialEq for Condition"],["impl StructuralPartialEq for PolicyError"],["impl StructuralPartialEq for ScriptContextEnum"],["impl StructuralPartialEq for KeychainKind"],["impl StructuralPartialEq for FeeRate"],["impl StructuralPartialEq for LocalUtxo"],["impl StructuralPartialEq for WeightedUtxo"],["impl StructuralPartialEq for Utxo"],["impl StructuralPartialEq for TransactionDetails"],["impl StructuralPartialEq for SignerId"],["impl StructuralPartialEq for SignerError"],["impl StructuralPartialEq for SignerContext"],["impl StructuralPartialEq for SignerOrdering"],["impl StructuralPartialEq for TapLeavesOptions"],["impl StructuralPartialEq for TxOrdering"],["impl StructuralPartialEq for ChangeSpendPolicy"],["impl StructuralPartialEq for AddressInfo"]], +"bdk_chain":[["impl<P> StructuralPartialEq for ChainGraph<P>"],["impl<P> StructuralPartialEq for ChangeSet<P>"],["impl<P> StructuralPartialEq for NewError<P>"],["impl<P> StructuralPartialEq for InsertTxError<P>"],["impl<P> StructuralPartialEq for UpdateError<P>"],["impl<P> StructuralPartialEq for UnresolvableConflict<P>"],["impl StructuralPartialEq for TxHeight"],["impl StructuralPartialEq for ConfirmationTime"],["impl StructuralPartialEq for BlockId"],["impl<I> StructuralPartialEq for FullTxOut<I>"],["impl<K> StructuralPartialEq for DerivationAdditions<K>"],["impl<K, P> StructuralPartialEq for KeychainScan<K, P>"],["impl StructuralPartialEq for Balance"],["impl<P> StructuralPartialEq for SparseChain<P>"],["impl<P> StructuralPartialEq for InsertTxError<P>"],["impl StructuralPartialEq for InsertCheckpointError"],["impl<P> StructuralPartialEq for UpdateError<P>"],["impl<P> StructuralPartialEq for ChangeSet<P>"],["impl StructuralPartialEq for TxGraph"],["impl StructuralPartialEq for Additions"]], +"bdk_coin_select":[["impl StructuralPartialEq for SelectionConstraint"],["impl StructuralPartialEq for ExcessStrategyKind"]], +"keychain_tracker_electrum_example":[["impl StructuralPartialEq for ScanOptions"]], +"keychain_tracker_esplora_example":[["impl StructuralPartialEq for ScanOptions"]], +"keychain_tracker_example_cli":[["impl StructuralPartialEq for Keychain"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js index 2bd48a00b0..dc30c1abba 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js @@ -1,3 +1,11 @@ (function() {var implementors = { -"bdk":[["impl Sync for Error",1,["bdk::error::Error"]],["impl Sync for AnyBlockchain",1,["bdk::blockchain::any::AnyBlockchain"]],["impl Sync for AnyBlockchainConfig",1,["bdk::blockchain::any::AnyBlockchainConfig"]],["impl Sync for ElectrumBlockchain",1,["bdk::blockchain::electrum::ElectrumBlockchain"]],["impl Sync for ElectrumBlockchainConfig",1,["bdk::blockchain::electrum::ElectrumBlockchainConfig"]],["impl Sync for RpcBlockchain",1,["bdk::blockchain::rpc::RpcBlockchain"]],["impl Sync for RpcConfig",1,["bdk::blockchain::rpc::RpcConfig"]],["impl Sync for RpcSyncParams",1,["bdk::blockchain::rpc::RpcSyncParams"]],["impl Sync for Auth",1,["bdk::blockchain::rpc::Auth"]],["impl Sync for RpcBlockchainFactory",1,["bdk::blockchain::rpc::RpcBlockchainFactory"]],["impl Sync for EsploraBlockchain",1,["bdk::blockchain::esplora::blocking::EsploraBlockchain"]],["impl Sync for EsploraBlockchainConfig",1,["bdk::blockchain::esplora::EsploraBlockchainConfig"]],["impl Sync for Mempool",1,["bdk::blockchain::compact_filters::peer::Mempool"]],["impl Sync for Peer",1,["bdk::blockchain::compact_filters::peer::Peer"]],["impl Sync for CompactFiltersBlockchain",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]],["impl Sync for BitcoinPeerConfig",1,["bdk::blockchain::compact_filters::BitcoinPeerConfig"]],["impl Sync for CompactFiltersBlockchainConfig",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]],["impl Sync for CompactFiltersError",1,["bdk::blockchain::compact_filters::CompactFiltersError"]],["impl Sync for Capability",1,["bdk::blockchain::Capability"]],["impl Sync for NoopProgress",1,["bdk::blockchain::NoopProgress"]],["impl Sync for LogProgress",1,["bdk::blockchain::LogProgress"]],["impl !Sync for AnyDatabase",1,["bdk::database::any::AnyDatabase"]],["impl !Sync for AnyBatch",1,["bdk::database::any::AnyBatch"]],["impl Sync for SledDbConfiguration",1,["bdk::database::any::SledDbConfiguration"]],["impl Sync for SqliteDbConfiguration",1,["bdk::database::any::SqliteDbConfiguration"]],["impl Sync for AnyDatabaseConfig",1,["bdk::database::any::AnyDatabaseConfig"]],["impl !Sync for SqliteDatabase",1,["bdk::database::sqlite::SqliteDatabase"]],["impl Sync for MemoryDatabase",1,["bdk::database::memory::MemoryDatabase"]],["impl Sync for SyncTime",1,["bdk::database::SyncTime"]],["impl Sync for Error",1,["bdk::descriptor::error::Error"]],["impl Sync for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Sync for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Sync for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Sync for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Sync for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Sync for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Sync for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Sync for P2Pkh<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Sync for P2Wpkh_P2Sh<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Sync for P2Wpkh<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Sync for Bip44<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Sync for Bip44Public<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Sync for Bip49<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Sync for Bip49Public<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Sync for Bip84<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Sync for Bip84Public<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl Sync for WordCount",1,["bdk::keys::bip39::WordCount"]],["impl<Ctx> Sync for DescriptorKey<Ctx>where
        Ctx: Sync,
    ",1,["bdk::keys::DescriptorKey"]],["impl Sync for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Sync for ExtendedKey<Ctx>where
        Ctx: Sync,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Sync for GeneratedKey<K, Ctx>where
        Ctx: Sync,
        K: Sync,
    ",1,["bdk::keys::GeneratedKey"]],["impl Sync for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Sync for KeyError",1,["bdk::keys::KeyError"]],["impl Sync for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Sync for FeeRate",1,["bdk::types::FeeRate"]],["impl Sync for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Sync for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Sync for Utxo",1,["bdk::types::Utxo"]],["impl Sync for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Sync for BlockTime",1,["bdk::types::BlockTime"]],["impl Sync for Balance",1,["bdk::types::Balance"]],["impl Sync for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Sync for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Sync for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Sync for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Sync for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Sync for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Sync for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Sync for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Sync for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Sync for SignerWrapper<S>where
        S: Sync,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Sync for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Sync for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Sync for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Sync for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Sync for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Sync for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !Sync for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Sync for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Sync for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Sync for VerifyError",1,["bdk::wallet::verify::VerifyError"]],["impl Sync for HWISigner",1,["bdk::wallet::hardwaresigner::HWISigner"]],["impl<D> !Sync for Wallet<D>",1,["bdk::wallet::Wallet"]],["impl Sync for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Sync for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl !Sync for SyncOptions",1,["bdk::wallet::SyncOptions"]]] +"bdk":[["impl Sync for Error",1,["bdk::error::Error"]],["impl Sync for Error",1,["bdk::descriptor::error::Error"]],["impl Sync for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Sync for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Sync for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Sync for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Sync for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Sync for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Sync for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Sync for P2Pkh<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Sync for P2Wpkh_P2Sh<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Sync for P2Wpkh<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Sync for Bip44<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Sync for Bip44Public<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Sync for Bip49<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Sync for Bip49Public<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Sync for Bip84<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Sync for Bip84Public<K>where
        K: Sync,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl<Ctx> Sync for DescriptorKey<Ctx>where
        Ctx: Sync,
    ",1,["bdk::keys::DescriptorKey"]],["impl Sync for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Sync for ExtendedKey<Ctx>where
        Ctx: Sync,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Sync for GeneratedKey<K, Ctx>where
        Ctx: Sync,
        K: Sync,
    ",1,["bdk::keys::GeneratedKey"]],["impl Sync for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Sync for KeyError",1,["bdk::keys::KeyError"]],["impl Sync for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Sync for FeeRate",1,["bdk::types::FeeRate"]],["impl Sync for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Sync for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Sync for Utxo",1,["bdk::types::Utxo"]],["impl Sync for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Sync for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Sync for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Sync for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Sync for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Sync for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Sync for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Sync for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Sync for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Sync for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Sync for SignerWrapper<S>where
        S: Sync,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Sync for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Sync for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Sync for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Sync for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Sync for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Sync for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !Sync for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Sync for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Sync for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl<D> Sync for Wallet<D>where
        D: Sync,
    ",1,["bdk::wallet::Wallet"]],["impl Sync for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Sync for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl<P> Sync for NewError<P>where
        P: Sync,
    ",1,["bdk::wallet::NewError"]]], +"bdk_chain":[["impl<P> Sync for ChainGraph<P>where
        P: Sync,
    ",1,["bdk_chain::chain_graph::ChainGraph"]],["impl<P> Sync for ChangeSet<P>where
        P: Sync,
    ",1,["bdk_chain::chain_graph::ChangeSet"]],["impl<P> Sync for NewError<P>where
        P: Sync,
    ",1,["bdk_chain::chain_graph::NewError"]],["impl<P> Sync for InsertTxError<P>where
        P: Sync,
    ",1,["bdk_chain::chain_graph::InsertTxError"]],["impl<P> Sync for UpdateError<P>where
        P: Sync,
    ",1,["bdk_chain::chain_graph::UpdateError"]],["impl<P> Sync for UnresolvableConflict<P>where
        P: Sync,
    ",1,["bdk_chain::chain_graph::UnresolvableConflict"]],["impl<I> Sync for SpkTxOutIndex<I>where
        I: Sync,
    ",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl Sync for TxHeight",1,["bdk_chain::chain_data::TxHeight"]],["impl Sync for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Sync for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl<I> Sync for FullTxOut<I>where
        I: Sync,
    ",1,["bdk_chain::chain_data::FullTxOut"]],["impl<K, P, B> Sync for Persist<K, P, B>where
        B: Sync,
        K: Sync,
        P: Sync,
    ",1,["bdk_chain::keychain::persist::Persist"]],["impl<K, P> Sync for KeychainTracker<K, P>where
        K: Sync,
        P: Sync,
    ",1,["bdk_chain::keychain::tracker::KeychainTracker"]],["impl<K> Sync for KeychainTxOutIndex<K>where
        K: Sync,
    ",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl<K> Sync for DerivationAdditions<K>where
        K: Sync,
    ",1,["bdk_chain::keychain::DerivationAdditions"]],["impl<K, P> Sync for KeychainScan<K, P>where
        K: Sync,
        P: Sync,
    ",1,["bdk_chain::keychain::KeychainScan"]],["impl<K, P> Sync for KeychainChangeSet<K, P>where
        K: Sync,
        P: Sync,
    ",1,["bdk_chain::keychain::KeychainChangeSet"]],["impl Sync for Balance",1,["bdk_chain::keychain::Balance"]],["impl<P> Sync for SparseChain<P>where
        P: Sync,
    ",1,["bdk_chain::sparse_chain::SparseChain"]],["impl<P> Sync for InsertTxError<P>where
        P: Sync,
    ",1,["bdk_chain::sparse_chain::InsertTxError"]],["impl Sync for InsertCheckpointError",1,["bdk_chain::sparse_chain::InsertCheckpointError"]],["impl<P> Sync for UpdateError<P>where
        P: Sync,
    ",1,["bdk_chain::sparse_chain::UpdateError"]],["impl<P> Sync for ChangeSet<P>where
        P: Sync,
    ",1,["bdk_chain::sparse_chain::ChangeSet"]],["impl Sync for TxGraph",1,["bdk_chain::tx_graph::TxGraph"]],["impl Sync for Additions",1,["bdk_chain::tx_graph::Additions"]],["impl<'g, F> Sync for TxDescendants<'g, F>where
        F: Sync,
    ",1,["bdk_chain::tx_graph::TxDescendants"]]], +"bdk_coin_select":[["impl Sync for WeightedValue",1,["bdk_coin_select::coin_selector::WeightedValue"]],["impl Sync for CoinSelectorOpt",1,["bdk_coin_select::coin_selector::CoinSelectorOpt"]],["impl<'a> Sync for CoinSelector<'a>",1,["bdk_coin_select::coin_selector::CoinSelector"]],["impl Sync for SelectionError",1,["bdk_coin_select::coin_selector::SelectionError"]],["impl Sync for SelectionConstraint",1,["bdk_coin_select::coin_selector::SelectionConstraint"]],["impl Sync for Selection",1,["bdk_coin_select::coin_selector::Selection"]],["impl Sync for ExcessStrategyKind",1,["bdk_coin_select::coin_selector::ExcessStrategyKind"]],["impl Sync for ExcessStrategy",1,["bdk_coin_select::coin_selector::ExcessStrategy"]],["impl Sync for BranchStrategy",1,["bdk_coin_select::bnb::BranchStrategy"]],["impl<'c, S> Sync for Bnb<'c, S>where
        S: Sync,
    ",1,["bdk_coin_select::bnb::Bnb"]],["impl<'c, 'f, S> !Sync for BnbIter<'c, 'f, S>",1,["bdk_coin_select::bnb::BnbIter"]],["impl Sync for BnbLimit",1,["bdk_coin_select::bnb::BnbLimit"]]], +"bdk_electrum":[["impl<K, P> Sync for ElectrumUpdate<K, P>where
        K: Sync,
        P: Sync,
    ",1,["bdk_electrum::ElectrumUpdate"]]], +"bdk_file_store":[["impl<K, P> Sync for KeychainStore<K, P>where
        K: Sync,
        P: Sync,
    ",1,["bdk_file_store::file_store::KeychainStore"]],["impl Sync for FileError",1,["bdk_file_store::file_store::FileError"]],["impl Sync for IterError",1,["bdk_file_store::file_store::IterError"]],["impl<'a, V> Sync for EntryIter<'a, V>where
        V: Sync,
    ",1,["bdk_file_store::file_store::EntryIter"]]], +"bdk_tmp_plan":[["impl<Ak> Sync for Requirements<Ak>where
        Ak: Sync,
    ",1,["bdk_tmp_plan::requirements::Requirements"]],["impl<Ak> Sync for RequiredSignatures<Ak>where
        Ak: Sync,
    ",1,["bdk_tmp_plan::requirements::RequiredSignatures"]],["impl Sync for SigningError",1,["bdk_tmp_plan::requirements::SigningError"]],["impl<Ak> Sync for PlanKey<Ak>where
        Ak: Sync,
    ",1,["bdk_tmp_plan::template::PlanKey"]],["impl<AK> Sync for Plan<AK>where
        AK: Sync,
    ",1,["bdk_tmp_plan::Plan"]],["impl Sync for SatisfactionMaterial",1,["bdk_tmp_plan::SatisfactionMaterial"]],["impl<Ak> Sync for PlanState<Ak>where
        Ak: Sync,
    ",1,["bdk_tmp_plan::PlanState"]],["impl<K> Sync for Assets<K>where
        K: Sync,
    ",1,["bdk_tmp_plan::Assets"]]], +"keychain_tracker_electrum_example":[["impl Sync for ElectrumCommands",1,["keychain_tracker_electrum_example::ElectrumCommands"]],["impl Sync for ScanOptions",1,["keychain_tracker_electrum_example::ScanOptions"]]], +"keychain_tracker_esplora_example":[["impl Sync for EsploraCommands",1,["keychain_tracker_esplora_example::EsploraCommands"]],["impl Sync for ScanOptions",1,["keychain_tracker_esplora_example::ScanOptions"]]], +"keychain_tracker_example_cli":[["impl<C> Sync for Args<C>where
        C: Sync,
    ",1,["keychain_tracker_example_cli::Args"]],["impl<C> Sync for Commands<C>where
        C: Sync,
    ",1,["keychain_tracker_example_cli::Commands"]],["impl Sync for CoinSelectionAlgo",1,["keychain_tracker_example_cli::CoinSelectionAlgo"]],["impl Sync for AddressCmd",1,["keychain_tracker_example_cli::AddressCmd"]],["impl Sync for TxOutCmd",1,["keychain_tracker_example_cli::TxOutCmd"]],["impl Sync for Keychain",1,["keychain_tracker_example_cli::Keychain"]],["impl Sync for AddrsOutput",1,["keychain_tracker_example_cli::AddrsOutput"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js index 881ca7c9dd..9d4e67c412 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js @@ -1,3 +1,11 @@ (function() {var implementors = { -"bdk":[["impl Unpin for Error",1,["bdk::error::Error"]],["impl Unpin for AnyBlockchain",1,["bdk::blockchain::any::AnyBlockchain"]],["impl Unpin for AnyBlockchainConfig",1,["bdk::blockchain::any::AnyBlockchainConfig"]],["impl Unpin for ElectrumBlockchain",1,["bdk::blockchain::electrum::ElectrumBlockchain"]],["impl Unpin for ElectrumBlockchainConfig",1,["bdk::blockchain::electrum::ElectrumBlockchainConfig"]],["impl Unpin for RpcBlockchain",1,["bdk::blockchain::rpc::RpcBlockchain"]],["impl Unpin for RpcConfig",1,["bdk::blockchain::rpc::RpcConfig"]],["impl Unpin for RpcSyncParams",1,["bdk::blockchain::rpc::RpcSyncParams"]],["impl Unpin for Auth",1,["bdk::blockchain::rpc::Auth"]],["impl Unpin for RpcBlockchainFactory",1,["bdk::blockchain::rpc::RpcBlockchainFactory"]],["impl Unpin for EsploraBlockchain",1,["bdk::blockchain::esplora::blocking::EsploraBlockchain"]],["impl Unpin for EsploraBlockchainConfig",1,["bdk::blockchain::esplora::EsploraBlockchainConfig"]],["impl Unpin for Mempool",1,["bdk::blockchain::compact_filters::peer::Mempool"]],["impl Unpin for Peer",1,["bdk::blockchain::compact_filters::peer::Peer"]],["impl Unpin for CompactFiltersBlockchain",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]],["impl Unpin for BitcoinPeerConfig",1,["bdk::blockchain::compact_filters::BitcoinPeerConfig"]],["impl Unpin for CompactFiltersBlockchainConfig",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]],["impl Unpin for CompactFiltersError",1,["bdk::blockchain::compact_filters::CompactFiltersError"]],["impl Unpin for Capability",1,["bdk::blockchain::Capability"]],["impl Unpin for NoopProgress",1,["bdk::blockchain::NoopProgress"]],["impl Unpin for LogProgress",1,["bdk::blockchain::LogProgress"]],["impl Unpin for AnyDatabase",1,["bdk::database::any::AnyDatabase"]],["impl Unpin for AnyBatch",1,["bdk::database::any::AnyBatch"]],["impl Unpin for SledDbConfiguration",1,["bdk::database::any::SledDbConfiguration"]],["impl Unpin for SqliteDbConfiguration",1,["bdk::database::any::SqliteDbConfiguration"]],["impl Unpin for AnyDatabaseConfig",1,["bdk::database::any::AnyDatabaseConfig"]],["impl Unpin for SqliteDatabase",1,["bdk::database::sqlite::SqliteDatabase"]],["impl Unpin for MemoryDatabase",1,["bdk::database::memory::MemoryDatabase"]],["impl Unpin for SyncTime",1,["bdk::database::SyncTime"]],["impl Unpin for Error",1,["bdk::descriptor::error::Error"]],["impl Unpin for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Unpin for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Unpin for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Unpin for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Unpin for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Unpin for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Unpin for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Unpin for P2Pkh<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Unpin for P2Wpkh_P2Sh<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Unpin for P2Wpkh<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Unpin for Bip44<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Unpin for Bip44Public<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Unpin for Bip49<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Unpin for Bip49Public<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Unpin for Bip84<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Unpin for Bip84Public<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl Unpin for WordCount",1,["bdk::keys::bip39::WordCount"]],["impl<Ctx> Unpin for DescriptorKey<Ctx>where
        Ctx: Unpin,
    ",1,["bdk::keys::DescriptorKey"]],["impl Unpin for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Unpin for ExtendedKey<Ctx>where
        Ctx: Unpin,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Unpin for GeneratedKey<K, Ctx>where
        Ctx: Unpin,
        K: Unpin,
    ",1,["bdk::keys::GeneratedKey"]],["impl Unpin for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Unpin for KeyError",1,["bdk::keys::KeyError"]],["impl Unpin for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Unpin for FeeRate",1,["bdk::types::FeeRate"]],["impl Unpin for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Unpin for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Unpin for Utxo",1,["bdk::types::Utxo"]],["impl Unpin for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Unpin for BlockTime",1,["bdk::types::BlockTime"]],["impl Unpin for Balance",1,["bdk::types::Balance"]],["impl Unpin for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Unpin for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Unpin for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Unpin for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Unpin for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Unpin for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Unpin for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Unpin for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Unpin for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Unpin for SignerWrapper<S>where
        S: Unpin,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Unpin for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Unpin for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Unpin for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Unpin for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Unpin for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Unpin for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> Unpin for TxBuilder<'a, D, Cs, Ctx>where
        Cs: Unpin,
        Ctx: Unpin,
    ",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Unpin for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Unpin for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Unpin for VerifyError",1,["bdk::wallet::verify::VerifyError"]],["impl Unpin for HWISigner",1,["bdk::wallet::hardwaresigner::HWISigner"]],["impl<D> Unpin for Wallet<D>where
        D: Unpin,
    ",1,["bdk::wallet::Wallet"]],["impl Unpin for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Unpin for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl Unpin for SyncOptions",1,["bdk::wallet::SyncOptions"]]] +"bdk":[["impl Unpin for Error",1,["bdk::error::Error"]],["impl Unpin for Error",1,["bdk::descriptor::error::Error"]],["impl Unpin for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl Unpin for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl Unpin for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl Unpin for Policy",1,["bdk::descriptor::policy::Policy"]],["impl Unpin for Condition",1,["bdk::descriptor::policy::Condition"]],["impl Unpin for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> Unpin for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> Unpin for P2Pkh<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> Unpin for P2Wpkh_P2Sh<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Unpin for P2Wpkh<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> Unpin for Bip44<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> Unpin for Bip44Public<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> Unpin for Bip49<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> Unpin for Bip49Public<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> Unpin for Bip84<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> Unpin for Bip84Public<K>where
        K: Unpin,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl<Ctx> Unpin for DescriptorKey<Ctx>where
        Ctx: Unpin,
    ",1,["bdk::keys::DescriptorKey"]],["impl Unpin for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> Unpin for ExtendedKey<Ctx>where
        Ctx: Unpin,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> Unpin for GeneratedKey<K, Ctx>where
        Ctx: Unpin,
        K: Unpin,
    ",1,["bdk::keys::GeneratedKey"]],["impl Unpin for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl Unpin for KeyError",1,["bdk::keys::KeyError"]],["impl Unpin for KeychainKind",1,["bdk::types::KeychainKind"]],["impl Unpin for FeeRate",1,["bdk::types::FeeRate"]],["impl Unpin for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl Unpin for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Unpin for Utxo",1,["bdk::types::Utxo"]],["impl Unpin for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl Unpin for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl Unpin for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl Unpin for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Unpin for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Unpin for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Unpin for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl Unpin for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl Unpin for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl Unpin for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> Unpin for SignerWrapper<S>where
        S: Unpin,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl Unpin for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl Unpin for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl Unpin for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl Unpin for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl Unpin for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl Unpin for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> Unpin for TxBuilder<'a, D, Cs, Ctx>where
        Cs: Unpin,
        Ctx: Unpin,
    ",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Unpin for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Unpin for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl<D> Unpin for Wallet<D>where
        D: Unpin,
    ",1,["bdk::wallet::Wallet"]],["impl Unpin for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl Unpin for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl<P> Unpin for NewError<P>where
        P: Unpin,
    ",1,["bdk::wallet::NewError"]]], +"bdk_chain":[["impl<P> Unpin for ChainGraph<P>where
        P: Unpin,
    ",1,["bdk_chain::chain_graph::ChainGraph"]],["impl<P> Unpin for ChangeSet<P>",1,["bdk_chain::chain_graph::ChangeSet"]],["impl<P> Unpin for NewError<P>where
        P: Unpin,
    ",1,["bdk_chain::chain_graph::NewError"]],["impl<P> Unpin for InsertTxError<P>where
        P: Unpin,
    ",1,["bdk_chain::chain_graph::InsertTxError"]],["impl<P> Unpin for UpdateError<P>where
        P: Unpin,
    ",1,["bdk_chain::chain_graph::UpdateError"]],["impl<P> Unpin for UnresolvableConflict<P>where
        P: Unpin,
    ",1,["bdk_chain::chain_graph::UnresolvableConflict"]],["impl<I> Unpin for SpkTxOutIndex<I>where
        I: Unpin,
    ",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl Unpin for TxHeight",1,["bdk_chain::chain_data::TxHeight"]],["impl Unpin for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Unpin for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl<I> Unpin for FullTxOut<I>where
        I: Unpin,
    ",1,["bdk_chain::chain_data::FullTxOut"]],["impl<K, P, B> Unpin for Persist<K, P, B>where
        B: Unpin,
    ",1,["bdk_chain::keychain::persist::Persist"]],["impl<K, P> Unpin for KeychainTracker<K, P>where
        K: Unpin,
        P: Unpin,
    ",1,["bdk_chain::keychain::tracker::KeychainTracker"]],["impl<K> Unpin for KeychainTxOutIndex<K>where
        K: Unpin,
    ",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl<K> Unpin for DerivationAdditions<K>",1,["bdk_chain::keychain::DerivationAdditions"]],["impl<K, P> Unpin for KeychainScan<K, P>where
        P: Unpin,
    ",1,["bdk_chain::keychain::KeychainScan"]],["impl<K, P> Unpin for KeychainChangeSet<K, P>",1,["bdk_chain::keychain::KeychainChangeSet"]],["impl Unpin for Balance",1,["bdk_chain::keychain::Balance"]],["impl<P> Unpin for SparseChain<P>where
        P: Unpin,
    ",1,["bdk_chain::sparse_chain::SparseChain"]],["impl<P> Unpin for InsertTxError<P>where
        P: Unpin,
    ",1,["bdk_chain::sparse_chain::InsertTxError"]],["impl Unpin for InsertCheckpointError",1,["bdk_chain::sparse_chain::InsertCheckpointError"]],["impl<P> Unpin for UpdateError<P>where
        P: Unpin,
    ",1,["bdk_chain::sparse_chain::UpdateError"]],["impl<P> Unpin for ChangeSet<P>",1,["bdk_chain::sparse_chain::ChangeSet"]],["impl Unpin for TxGraph",1,["bdk_chain::tx_graph::TxGraph"]],["impl Unpin for Additions",1,["bdk_chain::tx_graph::Additions"]],["impl<'g, F> Unpin for TxDescendants<'g, F>where
        F: Unpin,
    ",1,["bdk_chain::tx_graph::TxDescendants"]]], +"bdk_coin_select":[["impl Unpin for WeightedValue",1,["bdk_coin_select::coin_selector::WeightedValue"]],["impl Unpin for CoinSelectorOpt",1,["bdk_coin_select::coin_selector::CoinSelectorOpt"]],["impl<'a> Unpin for CoinSelector<'a>",1,["bdk_coin_select::coin_selector::CoinSelector"]],["impl Unpin for SelectionError",1,["bdk_coin_select::coin_selector::SelectionError"]],["impl Unpin for SelectionConstraint",1,["bdk_coin_select::coin_selector::SelectionConstraint"]],["impl Unpin for Selection",1,["bdk_coin_select::coin_selector::Selection"]],["impl Unpin for ExcessStrategyKind",1,["bdk_coin_select::coin_selector::ExcessStrategyKind"]],["impl Unpin for ExcessStrategy",1,["bdk_coin_select::coin_selector::ExcessStrategy"]],["impl Unpin for BranchStrategy",1,["bdk_coin_select::bnb::BranchStrategy"]],["impl<'c, S> Unpin for Bnb<'c, S>where
        S: Unpin,
    ",1,["bdk_coin_select::bnb::Bnb"]],["impl<'c, 'f, S> Unpin for BnbIter<'c, 'f, S>where
        S: Unpin,
        'c: 'f,
    ",1,["bdk_coin_select::bnb::BnbIter"]],["impl Unpin for BnbLimit",1,["bdk_coin_select::bnb::BnbLimit"]]], +"bdk_electrum":[["impl<K, P> Unpin for ElectrumUpdate<K, P>where
        P: Unpin,
    ",1,["bdk_electrum::ElectrumUpdate"]]], +"bdk_file_store":[["impl<K, P> Unpin for KeychainStore<K, P>where
        K: Unpin,
        P: Unpin,
    ",1,["bdk_file_store::file_store::KeychainStore"]],["impl Unpin for FileError",1,["bdk_file_store::file_store::FileError"]],["impl Unpin for IterError",1,["bdk_file_store::file_store::IterError"]],["impl<'a, V> Unpin for EntryIter<'a, V>where
        V: Unpin,
    ",1,["bdk_file_store::file_store::EntryIter"]]], +"bdk_tmp_plan":[["impl<Ak> Unpin for Requirements<Ak>where
        Ak: Unpin,
    ",1,["bdk_tmp_plan::requirements::Requirements"]],["impl<Ak> Unpin for RequiredSignatures<Ak>where
        Ak: Unpin,
    ",1,["bdk_tmp_plan::requirements::RequiredSignatures"]],["impl Unpin for SigningError",1,["bdk_tmp_plan::requirements::SigningError"]],["impl<Ak> Unpin for PlanKey<Ak>where
        Ak: Unpin,
    ",1,["bdk_tmp_plan::template::PlanKey"]],["impl<AK> Unpin for Plan<AK>where
        AK: Unpin,
    ",1,["bdk_tmp_plan::Plan"]],["impl Unpin for SatisfactionMaterial",1,["bdk_tmp_plan::SatisfactionMaterial"]],["impl<Ak> Unpin for PlanState<Ak>where
        Ak: Unpin,
    ",1,["bdk_tmp_plan::PlanState"]],["impl<K> Unpin for Assets<K>where
        K: Unpin,
    ",1,["bdk_tmp_plan::Assets"]]], +"keychain_tracker_electrum_example":[["impl Unpin for ElectrumCommands",1,["keychain_tracker_electrum_example::ElectrumCommands"]],["impl Unpin for ScanOptions",1,["keychain_tracker_electrum_example::ScanOptions"]]], +"keychain_tracker_esplora_example":[["impl Unpin for EsploraCommands",1,["keychain_tracker_esplora_example::EsploraCommands"]],["impl Unpin for ScanOptions",1,["keychain_tracker_esplora_example::ScanOptions"]]], +"keychain_tracker_example_cli":[["impl<C> Unpin for Args<C>where
        C: Unpin,
    ",1,["keychain_tracker_example_cli::Args"]],["impl<C> Unpin for Commands<C>where
        C: Unpin,
    ",1,["keychain_tracker_example_cli::Commands"]],["impl Unpin for CoinSelectionAlgo",1,["keychain_tracker_example_cli::CoinSelectionAlgo"]],["impl Unpin for AddressCmd",1,["keychain_tracker_example_cli::AddressCmd"]],["impl Unpin for TxOutCmd",1,["keychain_tracker_example_cli::TxOutCmd"]],["impl Unpin for Keychain",1,["keychain_tracker_example_cli::Keychain"]],["impl Unpin for AddrsOutput",1,["keychain_tracker_example_cli::AddrsOutput"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Add.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Add.js index 4f08fd7f53..2efa69ee34 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Add.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Add.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"bdk":[["impl Add<Balance> for Balance"]] +"bdk_chain":[["impl Add<Balance> for Balance"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js index 50fa85e102..dc6c5312e6 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js @@ -1,3 +1,4 @@ (function() {var implementors = { -"bdk":[["impl Deref for ElectrumBlockchain"],["impl Deref for RpcBlockchain"],["impl Deref for EsploraBlockchain"],["impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>"],["impl<S: Sized + Debug + Clone> Deref for SignerWrapper<S>"],["impl Deref for AddressInfo"]] +"bdk":[["impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>"],["impl<S: Sized + Debug + Clone> Deref for SignerWrapper<S>"],["impl Deref for AddressInfo"]], +"bdk_chain":[["impl<K> Deref for KeychainTxOutIndex<K>"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js index 8a71cae767..bf72d94f56 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -1,3 +1,11 @@ (function() {var implementors = { -"bdk":[["impl !RefUnwindSafe for Error",1,["bdk::error::Error"]],["impl !RefUnwindSafe for AnyBlockchain",1,["bdk::blockchain::any::AnyBlockchain"]],["impl RefUnwindSafe for AnyBlockchainConfig",1,["bdk::blockchain::any::AnyBlockchainConfig"]],["impl RefUnwindSafe for ElectrumBlockchain",1,["bdk::blockchain::electrum::ElectrumBlockchain"]],["impl RefUnwindSafe for ElectrumBlockchainConfig",1,["bdk::blockchain::electrum::ElectrumBlockchainConfig"]],["impl !RefUnwindSafe for RpcBlockchain",1,["bdk::blockchain::rpc::RpcBlockchain"]],["impl RefUnwindSafe for RpcConfig",1,["bdk::blockchain::rpc::RpcConfig"]],["impl RefUnwindSafe for RpcSyncParams",1,["bdk::blockchain::rpc::RpcSyncParams"]],["impl RefUnwindSafe for Auth",1,["bdk::blockchain::rpc::Auth"]],["impl RefUnwindSafe for RpcBlockchainFactory",1,["bdk::blockchain::rpc::RpcBlockchainFactory"]],["impl !RefUnwindSafe for EsploraBlockchain",1,["bdk::blockchain::esplora::blocking::EsploraBlockchain"]],["impl RefUnwindSafe for EsploraBlockchainConfig",1,["bdk::blockchain::esplora::EsploraBlockchainConfig"]],["impl RefUnwindSafe for Mempool",1,["bdk::blockchain::compact_filters::peer::Mempool"]],["impl !RefUnwindSafe for Peer",1,["bdk::blockchain::compact_filters::peer::Peer"]],["impl !RefUnwindSafe for CompactFiltersBlockchain",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]],["impl RefUnwindSafe for BitcoinPeerConfig",1,["bdk::blockchain::compact_filters::BitcoinPeerConfig"]],["impl RefUnwindSafe for CompactFiltersBlockchainConfig",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]],["impl !RefUnwindSafe for CompactFiltersError",1,["bdk::blockchain::compact_filters::CompactFiltersError"]],["impl RefUnwindSafe for Capability",1,["bdk::blockchain::Capability"]],["impl RefUnwindSafe for NoopProgress",1,["bdk::blockchain::NoopProgress"]],["impl RefUnwindSafe for LogProgress",1,["bdk::blockchain::LogProgress"]],["impl !RefUnwindSafe for AnyDatabase",1,["bdk::database::any::AnyDatabase"]],["impl !RefUnwindSafe for AnyBatch",1,["bdk::database::any::AnyBatch"]],["impl RefUnwindSafe for SledDbConfiguration",1,["bdk::database::any::SledDbConfiguration"]],["impl RefUnwindSafe for SqliteDbConfiguration",1,["bdk::database::any::SqliteDbConfiguration"]],["impl RefUnwindSafe for AnyDatabaseConfig",1,["bdk::database::any::AnyDatabaseConfig"]],["impl !RefUnwindSafe for SqliteDatabase",1,["bdk::database::sqlite::SqliteDatabase"]],["impl !RefUnwindSafe for MemoryDatabase",1,["bdk::database::memory::MemoryDatabase"]],["impl RefUnwindSafe for SyncTime",1,["bdk::database::SyncTime"]],["impl RefUnwindSafe for Error",1,["bdk::descriptor::error::Error"]],["impl RefUnwindSafe for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl RefUnwindSafe for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl RefUnwindSafe for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl RefUnwindSafe for Policy",1,["bdk::descriptor::policy::Policy"]],["impl RefUnwindSafe for Condition",1,["bdk::descriptor::policy::Condition"]],["impl RefUnwindSafe for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> RefUnwindSafe for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> RefUnwindSafe for P2Pkh<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> RefUnwindSafe for P2Wpkh_P2Sh<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> RefUnwindSafe for P2Wpkh<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> RefUnwindSafe for Bip44<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> RefUnwindSafe for Bip44Public<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> RefUnwindSafe for Bip49<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> RefUnwindSafe for Bip49Public<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> RefUnwindSafe for Bip84<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> RefUnwindSafe for Bip84Public<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl RefUnwindSafe for WordCount",1,["bdk::keys::bip39::WordCount"]],["impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx>where
        Ctx: RefUnwindSafe,
    ",1,["bdk::keys::DescriptorKey"]],["impl RefUnwindSafe for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> RefUnwindSafe for ExtendedKey<Ctx>where
        Ctx: RefUnwindSafe,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx>where
        Ctx: RefUnwindSafe,
        K: RefUnwindSafe,
    ",1,["bdk::keys::GeneratedKey"]],["impl RefUnwindSafe for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl RefUnwindSafe for KeyError",1,["bdk::keys::KeyError"]],["impl RefUnwindSafe for KeychainKind",1,["bdk::types::KeychainKind"]],["impl RefUnwindSafe for FeeRate",1,["bdk::types::FeeRate"]],["impl RefUnwindSafe for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl RefUnwindSafe for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl RefUnwindSafe for Utxo",1,["bdk::types::Utxo"]],["impl RefUnwindSafe for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl RefUnwindSafe for BlockTime",1,["bdk::types::BlockTime"]],["impl RefUnwindSafe for Balance",1,["bdk::types::Balance"]],["impl RefUnwindSafe for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl RefUnwindSafe for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl RefUnwindSafe for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl RefUnwindSafe for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl RefUnwindSafe for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl RefUnwindSafe for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl RefUnwindSafe for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl RefUnwindSafe for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl RefUnwindSafe for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> RefUnwindSafe for SignerWrapper<S>where
        S: RefUnwindSafe,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl RefUnwindSafe for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl !RefUnwindSafe for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl RefUnwindSafe for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl RefUnwindSafe for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl RefUnwindSafe for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl RefUnwindSafe for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !RefUnwindSafe for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl RefUnwindSafe for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl RefUnwindSafe for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl !RefUnwindSafe for VerifyError",1,["bdk::wallet::verify::VerifyError"]],["impl !RefUnwindSafe for HWISigner",1,["bdk::wallet::hardwaresigner::HWISigner"]],["impl<D> !RefUnwindSafe for Wallet<D>",1,["bdk::wallet::Wallet"]],["impl RefUnwindSafe for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl RefUnwindSafe for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl !RefUnwindSafe for SyncOptions",1,["bdk::wallet::SyncOptions"]]] +"bdk":[["impl RefUnwindSafe for Error",1,["bdk::error::Error"]],["impl RefUnwindSafe for Error",1,["bdk::descriptor::error::Error"]],["impl RefUnwindSafe for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl RefUnwindSafe for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl RefUnwindSafe for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl RefUnwindSafe for Policy",1,["bdk::descriptor::policy::Policy"]],["impl RefUnwindSafe for Condition",1,["bdk::descriptor::policy::Condition"]],["impl RefUnwindSafe for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> RefUnwindSafe for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> RefUnwindSafe for P2Pkh<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> RefUnwindSafe for P2Wpkh_P2Sh<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> RefUnwindSafe for P2Wpkh<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> RefUnwindSafe for Bip44<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> RefUnwindSafe for Bip44Public<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> RefUnwindSafe for Bip49<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> RefUnwindSafe for Bip49Public<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> RefUnwindSafe for Bip84<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> RefUnwindSafe for Bip84Public<K>where
        K: RefUnwindSafe,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx>where
        Ctx: RefUnwindSafe,
    ",1,["bdk::keys::DescriptorKey"]],["impl RefUnwindSafe for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> RefUnwindSafe for ExtendedKey<Ctx>where
        Ctx: RefUnwindSafe,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx>where
        Ctx: RefUnwindSafe,
        K: RefUnwindSafe,
    ",1,["bdk::keys::GeneratedKey"]],["impl RefUnwindSafe for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl RefUnwindSafe for KeyError",1,["bdk::keys::KeyError"]],["impl RefUnwindSafe for KeychainKind",1,["bdk::types::KeychainKind"]],["impl RefUnwindSafe for FeeRate",1,["bdk::types::FeeRate"]],["impl RefUnwindSafe for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl RefUnwindSafe for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl RefUnwindSafe for Utxo",1,["bdk::types::Utxo"]],["impl RefUnwindSafe for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl RefUnwindSafe for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl RefUnwindSafe for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl RefUnwindSafe for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl RefUnwindSafe for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl RefUnwindSafe for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl RefUnwindSafe for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl RefUnwindSafe for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl RefUnwindSafe for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl RefUnwindSafe for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> RefUnwindSafe for SignerWrapper<S>where
        S: RefUnwindSafe,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl RefUnwindSafe for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl !RefUnwindSafe for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl RefUnwindSafe for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl RefUnwindSafe for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl RefUnwindSafe for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl RefUnwindSafe for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !RefUnwindSafe for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl RefUnwindSafe for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl RefUnwindSafe for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl<D = ()> !RefUnwindSafe for Wallet<D>",1,["bdk::wallet::Wallet"]],["impl RefUnwindSafe for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl RefUnwindSafe for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl<P> RefUnwindSafe for NewError<P>where
        P: RefUnwindSafe,
    ",1,["bdk::wallet::NewError"]]], +"bdk_chain":[["impl<P> RefUnwindSafe for ChainGraph<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::ChainGraph"]],["impl<P> RefUnwindSafe for ChangeSet<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::ChangeSet"]],["impl<P> RefUnwindSafe for NewError<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::NewError"]],["impl<P> RefUnwindSafe for InsertTxError<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::InsertTxError"]],["impl<P> RefUnwindSafe for UpdateError<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::UpdateError"]],["impl<P> RefUnwindSafe for UnresolvableConflict<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::UnresolvableConflict"]],["impl<I> RefUnwindSafe for SpkTxOutIndex<I>where
        I: RefUnwindSafe,
    ",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl RefUnwindSafe for TxHeight",1,["bdk_chain::chain_data::TxHeight"]],["impl RefUnwindSafe for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl RefUnwindSafe for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl<I> RefUnwindSafe for FullTxOut<I>where
        I: RefUnwindSafe,
    ",1,["bdk_chain::chain_data::FullTxOut"]],["impl<K, P, B> RefUnwindSafe for Persist<K, P, B>where
        B: RefUnwindSafe,
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_chain::keychain::persist::Persist"]],["impl<K, P> RefUnwindSafe for KeychainTracker<K, P>where
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_chain::keychain::tracker::KeychainTracker"]],["impl<K> RefUnwindSafe for KeychainTxOutIndex<K>where
        K: RefUnwindSafe,
    ",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl<K> RefUnwindSafe for DerivationAdditions<K>where
        K: RefUnwindSafe,
    ",1,["bdk_chain::keychain::DerivationAdditions"]],["impl<K, P> RefUnwindSafe for KeychainScan<K, P>where
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_chain::keychain::KeychainScan"]],["impl<K, P> RefUnwindSafe for KeychainChangeSet<K, P>where
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_chain::keychain::KeychainChangeSet"]],["impl RefUnwindSafe for Balance",1,["bdk_chain::keychain::Balance"]],["impl<P> RefUnwindSafe for SparseChain<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::sparse_chain::SparseChain"]],["impl<P> RefUnwindSafe for InsertTxError<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::sparse_chain::InsertTxError"]],["impl RefUnwindSafe for InsertCheckpointError",1,["bdk_chain::sparse_chain::InsertCheckpointError"]],["impl<P> RefUnwindSafe for UpdateError<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::sparse_chain::UpdateError"]],["impl<P> RefUnwindSafe for ChangeSet<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::sparse_chain::ChangeSet"]],["impl RefUnwindSafe for TxGraph",1,["bdk_chain::tx_graph::TxGraph"]],["impl RefUnwindSafe for Additions",1,["bdk_chain::tx_graph::Additions"]],["impl<'g, F> RefUnwindSafe for TxDescendants<'g, F>where
        F: RefUnwindSafe,
    ",1,["bdk_chain::tx_graph::TxDescendants"]]], +"bdk_coin_select":[["impl RefUnwindSafe for WeightedValue",1,["bdk_coin_select::coin_selector::WeightedValue"]],["impl RefUnwindSafe for CoinSelectorOpt",1,["bdk_coin_select::coin_selector::CoinSelectorOpt"]],["impl<'a> RefUnwindSafe for CoinSelector<'a>",1,["bdk_coin_select::coin_selector::CoinSelector"]],["impl RefUnwindSafe for SelectionError",1,["bdk_coin_select::coin_selector::SelectionError"]],["impl RefUnwindSafe for SelectionConstraint",1,["bdk_coin_select::coin_selector::SelectionConstraint"]],["impl RefUnwindSafe for Selection",1,["bdk_coin_select::coin_selector::Selection"]],["impl RefUnwindSafe for ExcessStrategyKind",1,["bdk_coin_select::coin_selector::ExcessStrategyKind"]],["impl RefUnwindSafe for ExcessStrategy",1,["bdk_coin_select::coin_selector::ExcessStrategy"]],["impl RefUnwindSafe for BranchStrategy",1,["bdk_coin_select::bnb::BranchStrategy"]],["impl<'c, S> RefUnwindSafe for Bnb<'c, S>where
        S: RefUnwindSafe,
    ",1,["bdk_coin_select::bnb::Bnb"]],["impl<'c, 'f, S> !RefUnwindSafe for BnbIter<'c, 'f, S>",1,["bdk_coin_select::bnb::BnbIter"]],["impl RefUnwindSafe for BnbLimit",1,["bdk_coin_select::bnb::BnbLimit"]]], +"bdk_electrum":[["impl<K, P> RefUnwindSafe for ElectrumUpdate<K, P>where
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_electrum::ElectrumUpdate"]]], +"bdk_file_store":[["impl<K, P> RefUnwindSafe for KeychainStore<K, P>where
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_file_store::file_store::KeychainStore"]],["impl !RefUnwindSafe for FileError",1,["bdk_file_store::file_store::FileError"]],["impl !RefUnwindSafe for IterError",1,["bdk_file_store::file_store::IterError"]],["impl<'a, V> RefUnwindSafe for EntryIter<'a, V>where
        V: RefUnwindSafe,
    ",1,["bdk_file_store::file_store::EntryIter"]]], +"bdk_tmp_plan":[["impl<Ak> RefUnwindSafe for Requirements<Ak>where
        Ak: RefUnwindSafe,
    ",1,["bdk_tmp_plan::requirements::Requirements"]],["impl<Ak> RefUnwindSafe for RequiredSignatures<Ak>where
        Ak: RefUnwindSafe,
    ",1,["bdk_tmp_plan::requirements::RequiredSignatures"]],["impl RefUnwindSafe for SigningError",1,["bdk_tmp_plan::requirements::SigningError"]],["impl<Ak> RefUnwindSafe for PlanKey<Ak>where
        Ak: RefUnwindSafe,
    ",1,["bdk_tmp_plan::template::PlanKey"]],["impl<AK> RefUnwindSafe for Plan<AK>where
        AK: RefUnwindSafe,
    ",1,["bdk_tmp_plan::Plan"]],["impl RefUnwindSafe for SatisfactionMaterial",1,["bdk_tmp_plan::SatisfactionMaterial"]],["impl<Ak> RefUnwindSafe for PlanState<Ak>where
        Ak: RefUnwindSafe,
    ",1,["bdk_tmp_plan::PlanState"]],["impl<K> RefUnwindSafe for Assets<K>where
        K: RefUnwindSafe,
    ",1,["bdk_tmp_plan::Assets"]]], +"keychain_tracker_electrum_example":[["impl RefUnwindSafe for ElectrumCommands",1,["keychain_tracker_electrum_example::ElectrumCommands"]],["impl RefUnwindSafe for ScanOptions",1,["keychain_tracker_electrum_example::ScanOptions"]]], +"keychain_tracker_esplora_example":[["impl RefUnwindSafe for EsploraCommands",1,["keychain_tracker_esplora_example::EsploraCommands"]],["impl RefUnwindSafe for ScanOptions",1,["keychain_tracker_esplora_example::ScanOptions"]]], +"keychain_tracker_example_cli":[["impl<C> RefUnwindSafe for Args<C>where
        C: RefUnwindSafe,
    ",1,["keychain_tracker_example_cli::Args"]],["impl<C> RefUnwindSafe for Commands<C>where
        C: RefUnwindSafe,
    ",1,["keychain_tracker_example_cli::Commands"]],["impl RefUnwindSafe for CoinSelectionAlgo",1,["keychain_tracker_example_cli::CoinSelectionAlgo"]],["impl RefUnwindSafe for AddressCmd",1,["keychain_tracker_example_cli::AddressCmd"]],["impl RefUnwindSafe for TxOutCmd",1,["keychain_tracker_example_cli::TxOutCmd"]],["impl RefUnwindSafe for Keychain",1,["keychain_tracker_example_cli::Keychain"]],["impl RefUnwindSafe for AddrsOutput",1,["keychain_tracker_example_cli::AddrsOutput"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js index f3af7c52f6..d9a8b33f69 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js @@ -1,3 +1,11 @@ (function() {var implementors = { -"bdk":[["impl !UnwindSafe for Error",1,["bdk::error::Error"]],["impl !UnwindSafe for AnyBlockchain",1,["bdk::blockchain::any::AnyBlockchain"]],["impl UnwindSafe for AnyBlockchainConfig",1,["bdk::blockchain::any::AnyBlockchainConfig"]],["impl UnwindSafe for ElectrumBlockchain",1,["bdk::blockchain::electrum::ElectrumBlockchain"]],["impl UnwindSafe for ElectrumBlockchainConfig",1,["bdk::blockchain::electrum::ElectrumBlockchainConfig"]],["impl !UnwindSafe for RpcBlockchain",1,["bdk::blockchain::rpc::RpcBlockchain"]],["impl UnwindSafe for RpcConfig",1,["bdk::blockchain::rpc::RpcConfig"]],["impl UnwindSafe for RpcSyncParams",1,["bdk::blockchain::rpc::RpcSyncParams"]],["impl UnwindSafe for Auth",1,["bdk::blockchain::rpc::Auth"]],["impl UnwindSafe for RpcBlockchainFactory",1,["bdk::blockchain::rpc::RpcBlockchainFactory"]],["impl !UnwindSafe for EsploraBlockchain",1,["bdk::blockchain::esplora::blocking::EsploraBlockchain"]],["impl UnwindSafe for EsploraBlockchainConfig",1,["bdk::blockchain::esplora::EsploraBlockchainConfig"]],["impl UnwindSafe for Mempool",1,["bdk::blockchain::compact_filters::peer::Mempool"]],["impl !UnwindSafe for Peer",1,["bdk::blockchain::compact_filters::peer::Peer"]],["impl !UnwindSafe for CompactFiltersBlockchain",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]],["impl UnwindSafe for BitcoinPeerConfig",1,["bdk::blockchain::compact_filters::BitcoinPeerConfig"]],["impl UnwindSafe for CompactFiltersBlockchainConfig",1,["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]],["impl !UnwindSafe for CompactFiltersError",1,["bdk::blockchain::compact_filters::CompactFiltersError"]],["impl UnwindSafe for Capability",1,["bdk::blockchain::Capability"]],["impl UnwindSafe for NoopProgress",1,["bdk::blockchain::NoopProgress"]],["impl UnwindSafe for LogProgress",1,["bdk::blockchain::LogProgress"]],["impl !UnwindSafe for AnyDatabase",1,["bdk::database::any::AnyDatabase"]],["impl !UnwindSafe for AnyBatch",1,["bdk::database::any::AnyBatch"]],["impl UnwindSafe for SledDbConfiguration",1,["bdk::database::any::SledDbConfiguration"]],["impl UnwindSafe for SqliteDbConfiguration",1,["bdk::database::any::SqliteDbConfiguration"]],["impl UnwindSafe for AnyDatabaseConfig",1,["bdk::database::any::AnyDatabaseConfig"]],["impl !UnwindSafe for SqliteDatabase",1,["bdk::database::sqlite::SqliteDatabase"]],["impl !UnwindSafe for MemoryDatabase",1,["bdk::database::memory::MemoryDatabase"]],["impl UnwindSafe for SyncTime",1,["bdk::database::SyncTime"]],["impl UnwindSafe for Error",1,["bdk::descriptor::error::Error"]],["impl UnwindSafe for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl UnwindSafe for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl UnwindSafe for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl UnwindSafe for Policy",1,["bdk::descriptor::policy::Policy"]],["impl UnwindSafe for Condition",1,["bdk::descriptor::policy::Condition"]],["impl UnwindSafe for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> UnwindSafe for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> UnwindSafe for P2Pkh<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> UnwindSafe for P2Wpkh_P2Sh<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> UnwindSafe for P2Wpkh<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> UnwindSafe for Bip44<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> UnwindSafe for Bip44Public<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> UnwindSafe for Bip49<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> UnwindSafe for Bip49Public<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> UnwindSafe for Bip84<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> UnwindSafe for Bip84Public<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl UnwindSafe for WordCount",1,["bdk::keys::bip39::WordCount"]],["impl<Ctx> UnwindSafe for DescriptorKey<Ctx>where
        Ctx: UnwindSafe,
    ",1,["bdk::keys::DescriptorKey"]],["impl UnwindSafe for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> UnwindSafe for ExtendedKey<Ctx>where
        Ctx: UnwindSafe,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx>where
        Ctx: UnwindSafe,
        K: UnwindSafe,
    ",1,["bdk::keys::GeneratedKey"]],["impl UnwindSafe for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl UnwindSafe for KeyError",1,["bdk::keys::KeyError"]],["impl UnwindSafe for KeychainKind",1,["bdk::types::KeychainKind"]],["impl UnwindSafe for FeeRate",1,["bdk::types::FeeRate"]],["impl UnwindSafe for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl UnwindSafe for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl UnwindSafe for Utxo",1,["bdk::types::Utxo"]],["impl UnwindSafe for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl UnwindSafe for BlockTime",1,["bdk::types::BlockTime"]],["impl UnwindSafe for Balance",1,["bdk::types::Balance"]],["impl UnwindSafe for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl UnwindSafe for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl UnwindSafe for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl UnwindSafe for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl UnwindSafe for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl UnwindSafe for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl UnwindSafe for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl UnwindSafe for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl UnwindSafe for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> UnwindSafe for SignerWrapper<S>where
        S: UnwindSafe,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl UnwindSafe for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl !UnwindSafe for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl UnwindSafe for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl UnwindSafe for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl UnwindSafe for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl UnwindSafe for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !UnwindSafe for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl UnwindSafe for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl UnwindSafe for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl !UnwindSafe for VerifyError",1,["bdk::wallet::verify::VerifyError"]],["impl UnwindSafe for HWISigner",1,["bdk::wallet::hardwaresigner::HWISigner"]],["impl<D> !UnwindSafe for Wallet<D>",1,["bdk::wallet::Wallet"]],["impl UnwindSafe for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl UnwindSafe for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl !UnwindSafe for SyncOptions",1,["bdk::wallet::SyncOptions"]]] +"bdk":[["impl UnwindSafe for Error",1,["bdk::error::Error"]],["impl UnwindSafe for Error",1,["bdk::descriptor::error::Error"]],["impl UnwindSafe for PkOrF",1,["bdk::descriptor::policy::PkOrF"]],["impl UnwindSafe for SatisfiableItem",1,["bdk::descriptor::policy::SatisfiableItem"]],["impl UnwindSafe for Satisfaction",1,["bdk::descriptor::policy::Satisfaction"]],["impl UnwindSafe for Policy",1,["bdk::descriptor::policy::Policy"]],["impl UnwindSafe for Condition",1,["bdk::descriptor::policy::Condition"]],["impl UnwindSafe for PolicyError",1,["bdk::descriptor::policy::PolicyError"]],["impl<'a> UnwindSafe for BuildSatisfaction<'a>",1,["bdk::descriptor::policy::BuildSatisfaction"]],["impl<K> UnwindSafe for P2Pkh<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::P2Pkh"]],["impl<K> UnwindSafe for P2Wpkh_P2Sh<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> UnwindSafe for P2Wpkh<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::P2Wpkh"]],["impl<K> UnwindSafe for Bip44<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip44"]],["impl<K> UnwindSafe for Bip44Public<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip44Public"]],["impl<K> UnwindSafe for Bip49<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip49"]],["impl<K> UnwindSafe for Bip49Public<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip49Public"]],["impl<K> UnwindSafe for Bip84<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip84"]],["impl<K> UnwindSafe for Bip84Public<K>where
        K: UnwindSafe,
    ",1,["bdk::descriptor::template::Bip84Public"]],["impl<Ctx> UnwindSafe for DescriptorKey<Ctx>where
        Ctx: UnwindSafe,
    ",1,["bdk::keys::DescriptorKey"]],["impl UnwindSafe for ScriptContextEnum",1,["bdk::keys::ScriptContextEnum"]],["impl<Ctx> UnwindSafe for ExtendedKey<Ctx>where
        Ctx: UnwindSafe,
    ",1,["bdk::keys::ExtendedKey"]],["impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx>where
        Ctx: UnwindSafe,
        K: UnwindSafe,
    ",1,["bdk::keys::GeneratedKey"]],["impl UnwindSafe for PrivateKeyGenerateOptions",1,["bdk::keys::PrivateKeyGenerateOptions"]],["impl UnwindSafe for KeyError",1,["bdk::keys::KeyError"]],["impl UnwindSafe for KeychainKind",1,["bdk::types::KeychainKind"]],["impl UnwindSafe for FeeRate",1,["bdk::types::FeeRate"]],["impl UnwindSafe for LocalUtxo",1,["bdk::types::LocalUtxo"]],["impl UnwindSafe for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl UnwindSafe for Utxo",1,["bdk::types::Utxo"]],["impl UnwindSafe for TransactionDetails",1,["bdk::types::TransactionDetails"]],["impl UnwindSafe for Excess",1,["bdk::wallet::coin_selection::Excess"]],["impl UnwindSafe for CoinSelectionResult",1,["bdk::wallet::coin_selection::CoinSelectionResult"]],["impl UnwindSafe for LargestFirstCoinSelection",1,["bdk::wallet::coin_selection::LargestFirstCoinSelection"]],["impl UnwindSafe for OldestFirstCoinSelection",1,["bdk::wallet::coin_selection::OldestFirstCoinSelection"]],["impl UnwindSafe for BranchAndBoundCoinSelection",1,["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl UnwindSafe for FullyNodedExport",1,["bdk::wallet::export::FullyNodedExport"]],["impl UnwindSafe for SignerId",1,["bdk::wallet::signer::SignerId"]],["impl UnwindSafe for SignerError",1,["bdk::wallet::signer::SignerError"]],["impl UnwindSafe for SignerContext",1,["bdk::wallet::signer::SignerContext"]],["impl<S> UnwindSafe for SignerWrapper<S>where
        S: UnwindSafe,
    ",1,["bdk::wallet::signer::SignerWrapper"]],["impl UnwindSafe for SignerOrdering",1,["bdk::wallet::signer::SignerOrdering"]],["impl !UnwindSafe for SignersContainer",1,["bdk::wallet::signer::SignersContainer"]],["impl UnwindSafe for SignOptions",1,["bdk::wallet::signer::SignOptions"]],["impl UnwindSafe for TapLeavesOptions",1,["bdk::wallet::signer::TapLeavesOptions"]],["impl UnwindSafe for CreateTx",1,["bdk::wallet::tx_builder::CreateTx"]],["impl UnwindSafe for BumpFee",1,["bdk::wallet::tx_builder::BumpFee"]],["impl<'a, D, Cs, Ctx> !UnwindSafe for TxBuilder<'a, D, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl UnwindSafe for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl UnwindSafe for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl<D = ()> !UnwindSafe for Wallet<D>",1,["bdk::wallet::Wallet"]],["impl UnwindSafe for AddressIndex",1,["bdk::wallet::AddressIndex"]],["impl UnwindSafe for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl<P> UnwindSafe for NewError<P>where
        P: UnwindSafe,
    ",1,["bdk::wallet::NewError"]]], +"bdk_chain":[["impl<P> UnwindSafe for ChainGraph<P>where
        P: UnwindSafe + RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::ChainGraph"]],["impl<P> UnwindSafe for ChangeSet<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::chain_graph::ChangeSet"]],["impl<P> UnwindSafe for NewError<P>where
        P: UnwindSafe,
    ",1,["bdk_chain::chain_graph::NewError"]],["impl<P> UnwindSafe for InsertTxError<P>where
        P: UnwindSafe,
    ",1,["bdk_chain::chain_graph::InsertTxError"]],["impl<P> UnwindSafe for UpdateError<P>where
        P: UnwindSafe,
    ",1,["bdk_chain::chain_graph::UpdateError"]],["impl<P> UnwindSafe for UnresolvableConflict<P>where
        P: UnwindSafe,
    ",1,["bdk_chain::chain_graph::UnresolvableConflict"]],["impl<I> UnwindSafe for SpkTxOutIndex<I>where
        I: UnwindSafe + RefUnwindSafe,
    ",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl UnwindSafe for TxHeight",1,["bdk_chain::chain_data::TxHeight"]],["impl UnwindSafe for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl UnwindSafe for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl<I> UnwindSafe for FullTxOut<I>where
        I: UnwindSafe,
    ",1,["bdk_chain::chain_data::FullTxOut"]],["impl<K, P, B> UnwindSafe for Persist<K, P, B>where
        B: UnwindSafe,
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_chain::keychain::persist::Persist"]],["impl<K, P> UnwindSafe for KeychainTracker<K, P>where
        K: UnwindSafe + RefUnwindSafe,
        P: UnwindSafe + RefUnwindSafe,
    ",1,["bdk_chain::keychain::tracker::KeychainTracker"]],["impl<K> UnwindSafe for KeychainTxOutIndex<K>where
        K: UnwindSafe + RefUnwindSafe,
    ",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl<K> UnwindSafe for DerivationAdditions<K>where
        K: RefUnwindSafe,
    ",1,["bdk_chain::keychain::DerivationAdditions"]],["impl<K, P> UnwindSafe for KeychainScan<K, P>where
        K: RefUnwindSafe,
        P: UnwindSafe + RefUnwindSafe,
    ",1,["bdk_chain::keychain::KeychainScan"]],["impl<K, P> UnwindSafe for KeychainChangeSet<K, P>where
        K: RefUnwindSafe,
        P: RefUnwindSafe,
    ",1,["bdk_chain::keychain::KeychainChangeSet"]],["impl UnwindSafe for Balance",1,["bdk_chain::keychain::Balance"]],["impl<P> UnwindSafe for SparseChain<P>where
        P: UnwindSafe + RefUnwindSafe,
    ",1,["bdk_chain::sparse_chain::SparseChain"]],["impl<P> UnwindSafe for InsertTxError<P>where
        P: UnwindSafe,
    ",1,["bdk_chain::sparse_chain::InsertTxError"]],["impl UnwindSafe for InsertCheckpointError",1,["bdk_chain::sparse_chain::InsertCheckpointError"]],["impl<P> UnwindSafe for UpdateError<P>where
        P: UnwindSafe,
    ",1,["bdk_chain::sparse_chain::UpdateError"]],["impl<P> UnwindSafe for ChangeSet<P>where
        P: RefUnwindSafe,
    ",1,["bdk_chain::sparse_chain::ChangeSet"]],["impl UnwindSafe for TxGraph",1,["bdk_chain::tx_graph::TxGraph"]],["impl UnwindSafe for Additions",1,["bdk_chain::tx_graph::Additions"]],["impl<'g, F> UnwindSafe for TxDescendants<'g, F>where
        F: UnwindSafe,
    ",1,["bdk_chain::tx_graph::TxDescendants"]]], +"bdk_coin_select":[["impl UnwindSafe for WeightedValue",1,["bdk_coin_select::coin_selector::WeightedValue"]],["impl UnwindSafe for CoinSelectorOpt",1,["bdk_coin_select::coin_selector::CoinSelectorOpt"]],["impl<'a> UnwindSafe for CoinSelector<'a>",1,["bdk_coin_select::coin_selector::CoinSelector"]],["impl UnwindSafe for SelectionError",1,["bdk_coin_select::coin_selector::SelectionError"]],["impl UnwindSafe for SelectionConstraint",1,["bdk_coin_select::coin_selector::SelectionConstraint"]],["impl UnwindSafe for Selection",1,["bdk_coin_select::coin_selector::Selection"]],["impl UnwindSafe for ExcessStrategyKind",1,["bdk_coin_select::coin_selector::ExcessStrategyKind"]],["impl UnwindSafe for ExcessStrategy",1,["bdk_coin_select::coin_selector::ExcessStrategy"]],["impl UnwindSafe for BranchStrategy",1,["bdk_coin_select::bnb::BranchStrategy"]],["impl<'c, S> UnwindSafe for Bnb<'c, S>where
        S: UnwindSafe,
    ",1,["bdk_coin_select::bnb::Bnb"]],["impl<'c, 'f, S> !UnwindSafe for BnbIter<'c, 'f, S>",1,["bdk_coin_select::bnb::BnbIter"]],["impl UnwindSafe for BnbLimit",1,["bdk_coin_select::bnb::BnbLimit"]]], +"bdk_electrum":[["impl<K, P> UnwindSafe for ElectrumUpdate<K, P>where
        K: RefUnwindSafe,
        P: UnwindSafe + RefUnwindSafe,
    ",1,["bdk_electrum::ElectrumUpdate"]]], +"bdk_file_store":[["impl<K, P> UnwindSafe for KeychainStore<K, P>where
        K: UnwindSafe,
        P: UnwindSafe,
    ",1,["bdk_file_store::file_store::KeychainStore"]],["impl !UnwindSafe for FileError",1,["bdk_file_store::file_store::FileError"]],["impl !UnwindSafe for IterError",1,["bdk_file_store::file_store::IterError"]],["impl<'a, V> !UnwindSafe for EntryIter<'a, V>",1,["bdk_file_store::file_store::EntryIter"]]], +"bdk_tmp_plan":[["impl<Ak> UnwindSafe for Requirements<Ak>where
        Ak: UnwindSafe,
    ",1,["bdk_tmp_plan::requirements::Requirements"]],["impl<Ak> UnwindSafe for RequiredSignatures<Ak>where
        Ak: UnwindSafe,
    ",1,["bdk_tmp_plan::requirements::RequiredSignatures"]],["impl UnwindSafe for SigningError",1,["bdk_tmp_plan::requirements::SigningError"]],["impl<Ak> UnwindSafe for PlanKey<Ak>where
        Ak: UnwindSafe,
    ",1,["bdk_tmp_plan::template::PlanKey"]],["impl<AK> UnwindSafe for Plan<AK>where
        AK: UnwindSafe,
    ",1,["bdk_tmp_plan::Plan"]],["impl UnwindSafe for SatisfactionMaterial",1,["bdk_tmp_plan::SatisfactionMaterial"]],["impl<Ak> UnwindSafe for PlanState<Ak>where
        Ak: UnwindSafe,
    ",1,["bdk_tmp_plan::PlanState"]],["impl<K> UnwindSafe for Assets<K>where
        K: UnwindSafe,
    ",1,["bdk_tmp_plan::Assets"]]], +"keychain_tracker_electrum_example":[["impl UnwindSafe for ElectrumCommands",1,["keychain_tracker_electrum_example::ElectrumCommands"]],["impl UnwindSafe for ScanOptions",1,["keychain_tracker_electrum_example::ScanOptions"]]], +"keychain_tracker_esplora_example":[["impl UnwindSafe for EsploraCommands",1,["keychain_tracker_esplora_example::EsploraCommands"]],["impl UnwindSafe for ScanOptions",1,["keychain_tracker_esplora_example::ScanOptions"]]], +"keychain_tracker_example_cli":[["impl<C> UnwindSafe for Args<C>where
        C: UnwindSafe,
    ",1,["keychain_tracker_example_cli::Args"]],["impl<C> UnwindSafe for Commands<C>where
        C: UnwindSafe,
    ",1,["keychain_tracker_example_cli::Commands"]],["impl UnwindSafe for CoinSelectionAlgo",1,["keychain_tracker_example_cli::CoinSelectionAlgo"]],["impl UnwindSafe for AddressCmd",1,["keychain_tracker_example_cli::AddressCmd"]],["impl UnwindSafe for TxOutCmd",1,["keychain_tracker_example_cli::TxOutCmd"]],["impl UnwindSafe for Keychain",1,["keychain_tracker_example_cli::Keychain"]],["impl UnwindSafe for AddrsOutput",1,["keychain_tracker_example_cli::AddrsOutput"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js index ce96fcb022..4b898ef908 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js @@ -1,3 +1,4 @@ (function() {var implementors = { -"bdk":[["impl FromStr for FullyNodedExport"]] +"bdk":[["impl FromStr for FullyNodedExport"]], +"keychain_tracker_example_cli":[["impl FromStr for CoinSelectionAlgo"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js index 942ddb6a67..16aeca0c91 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js @@ -1,3 +1,5 @@ (function() {var implementors = { -"bdk":[["impl<'de> Deserialize<'de> for AnyBlockchainConfig"],["impl<'de> Deserialize<'de> for ElectrumBlockchainConfig"],["impl<'de> Deserialize<'de> for RpcConfig"],["impl<'de> Deserialize<'de> for RpcSyncParams"],["impl<'de> Deserialize<'de> for Auth"],["impl<'de> Deserialize<'de> for EsploraBlockchainConfig"],["impl<'de> Deserialize<'de> for BitcoinPeerConfig"],["impl<'de> Deserialize<'de> for CompactFiltersBlockchainConfig"],["impl<'de> Deserialize<'de> for SledDbConfiguration"],["impl<'de> Deserialize<'de> for SqliteDbConfiguration"],["impl<'de> Deserialize<'de> for AnyDatabaseConfig"],["impl<'de> Deserialize<'de> for SyncTime"],["impl<'de> Deserialize<'de> for KeychainKind"],["impl<'de> Deserialize<'de> for LocalUtxo"],["impl<'de> Deserialize<'de> for TransactionDetails"],["impl<'de> Deserialize<'de> for BlockTime"],["impl<'de> Deserialize<'de> for Balance"],["impl<'de> Deserialize<'de> for FullyNodedExport"]] +"bdk":[["impl<'de> Deserialize<'de> for KeychainKind"],["impl<'de> Deserialize<'de> for LocalUtxo"],["impl<'de> Deserialize<'de> for TransactionDetails"],["impl<'de> Deserialize<'de> for FullyNodedExport"]], +"bdk_chain":[["impl<'de, P> Deserialize<'de> for ChangeSet<P>where
        P: Deserialize<'de>,
    "],["impl<'de> Deserialize<'de> for TxHeight"],["impl<'de> Deserialize<'de> for ConfirmationTime"],["impl<'de> Deserialize<'de> for BlockId"],["impl<'de, K> Deserialize<'de> for DerivationAdditions<K>where
        K: Ord + Deserialize<'de>,
    "],["impl<'de, K, P> Deserialize<'de> for KeychainChangeSet<K, P>where
        K: Ord + Deserialize<'de>,
        P: Deserialize<'de>,
    "],["impl<'de> Deserialize<'de> for Balance"],["impl<'de, P> Deserialize<'de> for ChangeSet<P>where
        P: Deserialize<'de>,
    "],["impl<'de> Deserialize<'de> for Additions"]], +"keychain_tracker_example_cli":[["impl<'de> Deserialize<'de> for Keychain"],["impl<'de> Deserialize<'de> for AddrsOutput"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js index 67332f21ca..0eda849b2c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js @@ -1,3 +1,5 @@ (function() {var implementors = { -"bdk":[["impl Serialize for AnyBlockchainConfig"],["impl Serialize for ElectrumBlockchainConfig"],["impl Serialize for RpcConfig"],["impl Serialize for RpcSyncParams"],["impl Serialize for Auth"],["impl Serialize for EsploraBlockchainConfig"],["impl Serialize for BitcoinPeerConfig"],["impl Serialize for CompactFiltersBlockchainConfig"],["impl Serialize for SledDbConfiguration"],["impl Serialize for SqliteDbConfiguration"],["impl Serialize for AnyDatabaseConfig"],["impl Serialize for SyncTime"],["impl Serialize for PkOrF"],["impl Serialize for SatisfiableItem"],["impl Serialize for Satisfaction"],["impl Serialize for Policy"],["impl Serialize for Condition"],["impl Serialize for KeychainKind"],["impl Serialize for LocalUtxo"],["impl Serialize for TransactionDetails"],["impl Serialize for BlockTime"],["impl Serialize for Balance"],["impl Serialize for FullyNodedExport"]] +"bdk":[["impl Serialize for PkOrF"],["impl Serialize for SatisfiableItem"],["impl Serialize for Satisfaction"],["impl Serialize for Policy"],["impl Serialize for Condition"],["impl Serialize for KeychainKind"],["impl Serialize for LocalUtxo"],["impl Serialize for TransactionDetails"],["impl Serialize for FullyNodedExport"]], +"bdk_chain":[["impl<P> Serialize for ChangeSet<P>where
        P: Serialize,
    "],["impl Serialize for TxHeight"],["impl Serialize for ConfirmationTime"],["impl Serialize for BlockId"],["impl<K> Serialize for DerivationAdditions<K>where
        K: Ord + Serialize,
    "],["impl<K, P> Serialize for KeychainChangeSet<K, P>where
        K: Ord + Serialize,
        P: Serialize,
    "],["impl Serialize for Balance"],["impl<P> Serialize for ChangeSet<P>where
        P: Serialize,
    "],["impl Serialize for Additions"]], +"keychain_tracker_example_cli":[["impl Serialize for Keychain"],["impl Serialize for AddrsOutput"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/all.html new file mode 100644 index 0000000000..87be85a1d2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Structs

    Enums

    Functions

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/enum.ElectrumCommands.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/enum.ElectrumCommands.html new file mode 100644 index 0000000000..22a6248d83 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/enum.ElectrumCommands.html @@ -0,0 +1,24 @@ +ElectrumCommands in keychain_tracker_electrum_example - Rust
    pub(crate) enum ElectrumCommands {
    +    Scan {
    +        stop_gap: usize,
    +        scan_options: ScanOptions,
    +    },
    +    Sync {
    +        unused_spks: bool,
    +        all_spks: bool,
    +        utxos: bool,
    +        unconfirmed: bool,
    +        scan_options: ScanOptions,
    +    },
    +}

    Variants§

    §

    Scan

    Fields

    §stop_gap: usize

    When a gap this large has been found for a keychain it will stop.

    +
    §scan_options: ScanOptions

    Scans the addresses in the wallet using esplora API.

    +
    §

    Sync

    Fields

    §unused_spks: bool

    Scan all the unused addresses

    +
    §all_spks: bool

    Scan every address that you have derived

    +
    §utxos: bool

    Scan unspent outpoints for spends or changes to confirmation status of residing tx

    +
    §unconfirmed: bool

    Scan unconfirmed transactions for updates

    +
    §scan_options: ScanOptions

    Scans particular addresses using esplora API

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Test whether Self can parse a specific subcommand

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/fn.main.html new file mode 100644 index 0000000000..17c84c56c1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/fn.main.html @@ -0,0 +1 @@ +main in keychain_tracker_electrum_example - Rust
    pub(crate) fn main() -> Result<()>
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/index.html new file mode 100644 index 0000000000..61e3011028 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/index.html @@ -0,0 +1 @@ +keychain_tracker_electrum_example - Rust
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/sidebar-items.js new file mode 100644 index 0000000000..cdafc02ec3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["ElectrumCommands",""]],"fn":[["main",""]],"struct":[["ScanOptions",""]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/struct.ScanOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/struct.ScanOptions.html new file mode 100644 index 0000000000..09fcf1d00a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_electrum_example/struct.ScanOptions.html @@ -0,0 +1,10 @@ +ScanOptions in keychain_tracker_electrum_example - Rust
    pub struct ScanOptions {
    +    pub batch_size: usize,
    +}

    Fields§

    §batch_size: usize

    Set batch size for each script_history call to electrum client

    +

    Trait Implementations§

    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Deprecated, replaced with CommandFactory::command
    Deprecated, replaced with CommandFactory::command_for_update
    Build a [Command] that can instantiate Self. Read more
    Build a [Command] that can update self. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Parse from std::env::args_os(), exit on error
    Parse from std::env::args_os(), return Err on error.
    Parse from iterator, exit on error
    Parse from iterator, return Err on error.
    Update from iterator, exit on error
    Update from iterator, return Err on error.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/all.html new file mode 100644 index 0000000000..466d67d62e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Structs

    Enums

    Functions

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/enum.EsploraCommands.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/enum.EsploraCommands.html new file mode 100644 index 0000000000..489169199e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/enum.EsploraCommands.html @@ -0,0 +1,28 @@ +EsploraCommands in keychain_tracker_esplora_example - Rust
    pub(crate) enum EsploraCommands {
    +    Scan {
    +        stop_gap: usize,
    +        scan_options: ScanOptions,
    +    },
    +    Sync {
    +        unused_spks: bool,
    +        all_spks: bool,
    +        utxos: bool,
    +        unconfirmed: bool,
    +        scan_options: ScanOptions,
    +    },
    +}

    Variants§

    §

    Scan

    Fields

    §stop_gap: usize

    When a gap this large has been found for a keychain it will stop.

    +
    §scan_options: ScanOptions

    Scans the addresses in the wallet using esplora API.

    +
    §

    Sync

    Fields

    §unused_spks: bool

    Scan all the unused addresses

    +
    §all_spks: bool

    Scan every address that you have derived

    +
    §utxos: bool

    Scan unspent outpoints for spends or changes to confirmation status of residing tx

    +
    §unconfirmed: bool

    Scan unconfirmed transactions for updates

    +
    §scan_options: ScanOptions

    Scans particular addresses using esplora API

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Test whether Self can parse a specific subcommand

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +
    Instruments this type with the provided Span, returning an +Instrumented wrapper. Read more
    Instruments this type with the current Span, returning an +Instrumented wrapper. Read more

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a +WithDispatch wrapper. Read more
    Attaches the current default Subscriber to this type, returning a +WithDispatch wrapper. Read more
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/fn.main.html new file mode 100644 index 0000000000..160705632f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/fn.main.html @@ -0,0 +1 @@ +main in keychain_tracker_esplora_example - Rust
    pub(crate) fn main() -> Result<()>
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/index.html new file mode 100644 index 0000000000..637b49cfb4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/index.html @@ -0,0 +1 @@ +keychain_tracker_esplora_example - Rust
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/sidebar-items.js new file mode 100644 index 0000000000..130d54f1e1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["EsploraCommands",""]],"fn":[["main",""]],"struct":[["ScanOptions",""]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/struct.ScanOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/struct.ScanOptions.html new file mode 100644 index 0000000000..eb2e201057 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_esplora_example/struct.ScanOptions.html @@ -0,0 +1,13 @@ +ScanOptions in keychain_tracker_esplora_example - Rust
    pub struct ScanOptions {
    +    pub parallel_requests: usize,
    +}

    Fields§

    §parallel_requests: usize

    Trait Implementations§

    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Deprecated, replaced with CommandFactory::command
    Deprecated, replaced with CommandFactory::command_for_update
    Build a [Command] that can instantiate Self. Read more
    Build a [Command] that can update self. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Parse from std::env::args_os(), exit on error
    Parse from std::env::args_os(), return Err on error.
    Parse from iterator, exit on error
    Parse from iterator, return Err on error.
    Update from iterator, exit on error
    Update from iterator, return Err on error.
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +
    Instruments this type with the provided Span, returning an +Instrumented wrapper. Read more
    Instruments this type with the current Span, returning an +Instrumented wrapper. Read more

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a +WithDispatch wrapper. Read more
    Attaches the current default Subscriber to this type, returning a +WithDispatch wrapper. Read more
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/all.html new file mode 100644 index 0000000000..fb1892946a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/all.html @@ -0,0 +1 @@ +List of all items in this crate
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.AddressCmd.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.AddressCmd.html new file mode 100644 index 0000000000..8f318a9788 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.AddressCmd.html @@ -0,0 +1,15 @@ +AddressCmd in keychain_tracker_example_cli - Rust
    pub enum AddressCmd {
    +    Next,
    +    New,
    +    List {
    +        change: bool,
    +    },
    +    Index,
    +}

    Variants§

    §

    Next

    Get the next unused address

    +
    §

    New

    Get a new address regardless if the existing ones haven’t been used

    +
    §

    List

    Fields

    §change: bool

    List all addresses

    +
    §

    Index

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Test whether Self can parse a specific subcommand

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.CoinSelectionAlgo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.CoinSelectionAlgo.html new file mode 100644 index 0000000000..186d3186be --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.CoinSelectionAlgo.html @@ -0,0 +1,11 @@ +CoinSelectionAlgo in keychain_tracker_example_cli - Rust
    pub enum CoinSelectionAlgo {
    +    LargestFirst,
    +    SmallestFirst,
    +    OldestFirst,
    +    NewestFirst,
    +    BranchAndBound,
    +}

    Variants§

    §

    LargestFirst

    §

    SmallestFirst

    §

    OldestFirst

    §

    NewestFirst

    §

    BranchAndBound

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Formats the value using the given formatter. Read more
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.Commands.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.Commands.html new file mode 100644 index 0000000000..0d66266e46 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.Commands.html @@ -0,0 +1,23 @@ +Commands in keychain_tracker_example_cli - Rust
    pub enum Commands<C: Subcommand> {
    +    ChainSpecific(C),
    +    Address {
    +        addr_cmd: AddressCmd,
    +    },
    +    Balance,
    +    TxOut {
    +        txout_cmd: TxOutCmd,
    +    },
    +    Send {
    +        value: u64,
    +        address: Address,
    +        coin_select: CoinSelectionAlgo,
    +    },
    +}

    Variants§

    §

    ChainSpecific(C)

    §

    Address

    Fields

    §addr_cmd: AddressCmd

    Address generation and inspection

    +
    §

    Balance

    Get the wallet balance

    +
    §

    TxOut

    Fields

    §txout_cmd: TxOutCmd

    TxOut related commands

    +
    §

    Send

    Fields

    §value: u64
    §address: Address
    §coin_select: CoinSelectionAlgo

    Send coins to an address

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Test whether Self can parse a specific subcommand

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.Keychain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.Keychain.html new file mode 100644 index 0000000000..bb0741a39a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.Keychain.html @@ -0,0 +1,12 @@ +Keychain in keychain_tracker_example_cli - Rust
    pub enum Keychain {
    +    External,
    +    Internal,
    +}

    Variants§

    §

    External

    §

    Internal

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used +by ==. Read more
    This method tests for !=. The default implementation is almost always +sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more
    This method tests greater than (for self and other) and is used by the > operator. Read more
    This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more
    Compare self to key and return true if they are equal.

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    Converts the given value to a String. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.TxOutCmd.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.TxOutCmd.html new file mode 100644 index 0000000000..6c0717aabd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/enum.TxOutCmd.html @@ -0,0 +1,16 @@ +TxOutCmd in keychain_tracker_example_cli - Rust
    pub enum TxOutCmd {
    +    List {
    +        spent: bool,
    +        unspent: bool,
    +        confirmed: bool,
    +        unconfirmed: bool,
    +    },
    +}

    Variants§

    §

    List

    Fields

    §spent: bool

    Return only spent outputs

    +
    §unspent: bool

    Return only unspent outputs

    +
    §confirmed: bool

    Return only confirmed outputs

    +
    §unconfirmed: bool

    Return only unconfirmed outputs

    +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Test whether Self can parse a specific subcommand

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.create_tx.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.create_tx.html new file mode 100644 index 0000000000..28be428b07 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.create_tx.html @@ -0,0 +1 @@ +create_tx in keychain_tracker_example_cli - Rust
    pub fn create_tx<P: ChainPosition>(
        value: u64,
        address: Address,
        coin_select: CoinSelectionAlgo,
        keychain_tracker: &mut KeychainTracker<Keychain, P>,
        keymap: &HashMap<DescriptorPublicKey, DescriptorSecretKey>
    ) -> Result<(Transaction, Option<(DerivationAdditions<Keychain>, (Keychain, u32))>)>
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.handle_commands.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.handle_commands.html new file mode 100644 index 0000000000..202a399919 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.handle_commands.html @@ -0,0 +1 @@ +handle_commands in keychain_tracker_example_cli - Rust
    pub fn handle_commands<C: Subcommand, P>(
        command: Commands<C>,
        broadcast: impl FnOnce(&Transaction) -> Result<()>,
        tracker: &Mutex<KeychainTracker<Keychain, P>>,
        store: &Mutex<KeychainStore<Keychain, P>>,
        network: Network,
        keymap: &HashMap<DescriptorPublicKey, DescriptorSecretKey>
    ) -> Result<()>where
        P: ChainPosition,
        KeychainChangeSet<Keychain, P>: Serialize + DeserializeOwned,
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.init.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.init.html new file mode 100644 index 0000000000..a83c6a369e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.init.html @@ -0,0 +1 @@ +init in keychain_tracker_example_cli - Rust
    pub fn init<C: Subcommand, P>(
    ) -> Result<(Args<C>, KeyMap, Mutex<KeychainTracker<Keychain, P>>, Mutex<KeychainStore<Keychain, P>>)>where
        P: ChainPosition,
        KeychainChangeSet<Keychain, P>: Serialize + DeserializeOwned,
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.planned_utxos.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.planned_utxos.html new file mode 100644 index 0000000000..e3273eed53 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.planned_utxos.html @@ -0,0 +1 @@ +planned_utxos in keychain_tracker_example_cli - Rust
    pub fn planned_utxos<'a, AK: CanDerive + Clone, P: ChainPosition>(
        tracker: &'a KeychainTracker<Keychain, P>,
        assets: &'a Assets<AK>
    ) -> impl Iterator<Item = (Plan<AK>, FullTxOut<P>)> + 'a
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_address_cmd.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_address_cmd.html new file mode 100644 index 0000000000..802339a1bc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_address_cmd.html @@ -0,0 +1 @@ +run_address_cmd in keychain_tracker_example_cli - Rust
    pub fn run_address_cmd<P>(
        tracker: &Mutex<KeychainTracker<Keychain, P>>,
        db: &Mutex<KeychainStore<Keychain, P>>,
        addr_cmd: AddressCmd,
        network: Network
    ) -> Result<()>where
        P: ChainPosition,
        KeychainChangeSet<Keychain, P>: Serialize + DeserializeOwned,
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_balance_cmd.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_balance_cmd.html new file mode 100644 index 0000000000..a7f2cb5a7d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_balance_cmd.html @@ -0,0 +1 @@ +run_balance_cmd in keychain_tracker_example_cli - Rust
    pub fn run_balance_cmd<P: ChainPosition>(
        tracker: &Mutex<KeychainTracker<Keychain, P>>
    )
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_txo_cmd.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_txo_cmd.html new file mode 100644 index 0000000000..4fc98f33c6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/fn.run_txo_cmd.html @@ -0,0 +1 @@ +run_txo_cmd in keychain_tracker_example_cli - Rust
    pub fn run_txo_cmd<K: Debug + Clone + Ord, P: ChainPosition>(
        txout_cmd: TxOutCmd,
        tracker: &Mutex<KeychainTracker<K, P>>,
        network: Network
    )
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/index.html new file mode 100644 index 0000000000..d2b14bdc88 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/index.html @@ -0,0 +1 @@ +keychain_tracker_example_cli - Rust
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/sidebar-items.js new file mode 100644 index 0000000000..9e66c98215 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["AddressCmd",""],["CoinSelectionAlgo",""],["Commands",""],["Keychain",""],["TxOutCmd",""]],"externcrate":[["anyhow",""]],"fn":[["create_tx",""],["handle_commands",""],["init",""],["planned_utxos",""],["run_address_cmd",""],["run_balance_cmd",""],["run_txo_cmd",""]],"struct":[["AddrsOutput","A structure defining output of a AddressCmd execution."],["Args",""]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/struct.AddrsOutput.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/struct.AddrsOutput.html new file mode 100644 index 0000000000..dfd44b09d5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/struct.AddrsOutput.html @@ -0,0 +1,6 @@ +AddrsOutput in keychain_tracker_example_cli - Rust
    pub struct AddrsOutput { /* private fields */ }
    Expand description

    A structure defining output of a AddressCmd execution.

    +

    Trait Implementations§

    Deserialize this value from the given Serde deserializer. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/struct.Args.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/struct.Args.html new file mode 100644 index 0000000000..2df01e9fea --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/keychain_tracker_example_cli/struct.Args.html @@ -0,0 +1,12 @@ +Args in keychain_tracker_example_cli - Rust
    pub struct Args<C: Subcommand> {
    +    pub descriptor: String,
    +    pub change_descriptor: Option<String>,
    +    pub network: Network,
    +    pub db_path: PathBuf,
    +    pub cp_limit: usize,
    +    pub command: Commands<C>,
    +}

    Fields§

    §descriptor: String§change_descriptor: Option<String>§network: Network§db_path: PathBuf§cp_limit: usize§command: Commands<C>

    Trait Implementations§

    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Deprecated, replaced with CommandFactory::command
    Deprecated, replaced with CommandFactory::command_for_update
    Build a [Command] that can instantiate Self. Read more
    Build a [Command] that can update self. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Parse from std::env::args_os(), exit on error
    Parse from std::env::args_os(), return Err on error.
    Parse from iterator, exit on error
    Parse from iterator, return Err on error.
    Update from iterator, exit on error
    Update from iterator, return Err on error.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Calls U::from(self).

    +

    That is, this conversion is whatever the implementation of +From<T> for U chooses to do.

    +
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search-index.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search-index.js index 04d7cfff27..ae9d1f9a40 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search-index.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search-index.js @@ -1,5 +1,17 @@ var searchIndex = JSON.parse('{\ -"bdk":{"doc":"A modern, lightweight, descriptor-based wallet library …","t":[3,13,3,13,13,13,13,6,13,13,13,4,13,13,3,13,13,13,13,13,2,13,13,13,13,13,13,13,13,13,13,13,4,13,3,13,13,13,13,13,13,13,13,13,13,13,13,13,13,2,13,13,13,2,13,3,13,2,13,4,8,13,2,3,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,14,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,0,11,11,12,11,11,11,11,0,12,12,12,11,11,11,11,11,2,11,11,2,12,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,11,11,11,11,11,11,11,11,11,12,12,10,5,11,11,11,11,11,11,11,11,11,0,11,12,12,12,12,12,12,12,12,13,2,2,8,8,4,2,16,8,2,2,3,13,13,8,8,8,16,3,3,8,6,2,2,8,8,0,11,11,11,11,11,11,10,10,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,0,11,0,10,11,11,11,11,11,11,10,10,10,11,10,10,11,11,11,11,11,11,11,5,5,5,0,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,10,11,4,4,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,3,13,3,3,4,13,13,13,13,13,13,13,13,3,13,13,13,3,13,13,13,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,12,11,11,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,12,12,11,11,11,11,11,11,11,12,12,11,11,11,13,3,3,4,13,13,13,13,13,13,13,13,13,13,12,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,4,13,13,3,3,3,3,13,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,12,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,12,12,11,12,12,12,2,2,16,8,8,16,8,8,2,3,3,0,10,11,12,11,11,11,11,10,11,11,11,10,11,12,10,11,10,11,10,11,10,11,10,11,10,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,11,11,11,11,10,11,10,11,10,11,10,11,0,11,12,11,10,11,10,11,10,11,10,11,10,11,10,11,11,11,11,11,11,11,11,11,11,4,4,4,13,13,13,13,13,13,3,13,13,13,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,6,4,2,4,3,6,8,13,6,8,16,6,4,3,13,13,2,8,4,13,13,6,13,13,4,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,10,11,11,0,11,11,11,11,11,11,11,11,11,11,11,10,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,5,5,5,5,13,13,4,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,13,13,4,13,3,6,13,13,6,13,13,13,13,13,13,13,13,13,13,13,4,3,4,13,13,13,13,13,4,4,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,12,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3,3,3,3,3,8,6,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,8,4,4,4,16,16,8,4,13,8,8,3,8,13,13,13,16,4,6,13,13,13,16,13,3,13,8,4,13,13,13,3,3,4,3,13,6,13,13,13,5,10,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11,5,11,10,11,11,5,10,11,12,12,11,11,11,11,11,11,10,12,11,11,11,11,10,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,13,13,13,4,13,4,3,6,13,4,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,8,10,10,10,4,3,8,13,13,13,13,3,3,11,12,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,11,11,0,12,11,11,11,11,11,11,11,11,10,11,12,11,11,11,11,11,11,12,11,11,11,0,11,0,11,11,11,11,11,11,11,11,11,0,11,11,11,11,0,11,11,11,11,5,3,13,8,3,6,4,3,13,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,3,6,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,13,13,13,13,13,13,8,13,13,13,13,13,13,13,13,13,13,13,13,13,13,3,8,4,4,4,3,3,3,13,4,8,13,11,12,12,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,10,11,11,10,11,12,11,12,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,5,13,3,13,13,4,3,13,13,3,8,4,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,13,13,13,4,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11],"n":["Balance","Bip32","BlockTime","BnBNoExactMatch","BnBTotalTriesExceeded","ChecksumMismatch","CompactFilters","ConfirmationTime","Descriptor","Electrum","Encode","Error","Esplora","External","FeeRate","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","Foreign","Generic","HdKeyPaths","Hex","InsufficientFunds","Internal","InvalidNetwork","InvalidOutpoint","InvalidPolicyPathError","InvalidProgressValue","InvalidU32Bytes","IrreplaceableTransaction","Json","Key","KeychainKind","Local","LocalUtxo","Miniscript","MiniscriptPsbt","MissingCachedScripts","MissingKeyOrigin","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","ProgressUpdateError","Psbt","PsbtParse","Rpc","Rusqlite","ScriptDoesntHaveAddressForm","Secp256k1","SignOptions","Signer","Sled","SpendingPolicyRequired","SyncOptions","TransactionConfirmed","TransactionDetails","TransactionNotFound","TxBuilder","UnknownUtxo","Utxo","Vbytes","Verification","Wallet","WeightedUtxo","add","as_byte","as_ref","as_sat_per_vb","base32_len","blockchain","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_base32","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","confirmation_time","confirmed","database","default","default","default","default_min_relay_fee","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","descriptor","descriptor","deserialize","deserialize","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","eq","eq","fee","fee_vb","fee_wu","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fragment","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_btc_per_kvb","from_sat_per_kvb","from_sat_per_kwu","from_sat_per_vb","from_vb","from_wu","get_hash","get_hash","get_spendable","get_total","hash","hash","height","immature","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","is_spent","keychain","keys","new","outpoint","outpoint","partial_cmp","partial_cmp","partial_cmp","provide","psbt","received","satisfaction_weight","sent","serialize","serialize","serialize","serialize","serialize","signer","sub","sum","template","timestamp","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","transaction","trusted_pending","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","txid","txout","txout","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","untrusted_pending","utxo","vbytes","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet","write_base32","available","found","needed","requested","required","required","outpoint","psbt_input","AccurateFees","AnyBlockchain","AnyBlockchainConfig","Blockchain","BlockchainFactory","Capability","CompactFiltersBlockchain","Config","ConfigurableBlockchain","ElectrumBlockchain","ElectrumBlockchainConfig","EsploraBlockchain","FullHistory","GetAnyTx","GetBlockHash","GetHeight","GetTx","Inner","LogProgress","NoopProgress","Progress","ProgressData","RpcBlockchain","RpcConfig","StatelessBlockchain","WalletSync","any","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","broadcast","build","build_for_wallet","clone","clone","clone","clone_into","clone_into","clone_into","compact_filters","default","default","deref","deref","deref","deref_mut","deref_mut","deref_mut","drop","drop","drop","electrum","eq","esplora","estimate_fee","fmt","fmt","fmt","from","from","from","from_config","get_block_hash","get_capabilities","get_hash","get_height","get_tx","hash","init","init","init","into","into","into","log_progress","noop_progress","progress","rpc","sync_wallet","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","update","update","update","vzip","vzip","vzip","wallet_setup","wallet_sync","AnyBlockchain","AnyBlockchainConfig","CompactFilters","CompactFilters","Electrum","Electrum","Esplora","Esplora","Rpc","Rpc","borrow","borrow","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref_mut","deref_mut","deserialize","drop","drop","eq","estimate_fee","fmt","from","from","from","from","from","from","from","from","from","from","from_config","get_block_hash","get_capabilities","get_height","get_tx","init","init","into","into","serialize","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","wallet_setup","wallet_sync","Bip158","BitcoinPeerConfig","BlockHashNotFound","CompactFiltersBlockchain","CompactFiltersBlockchainConfig","CompactFiltersError","DataCorruption","Db","Global","InvalidFilter","InvalidFilterHeader","InvalidHeaders","InvalidResponse","Io","Mempool","MissingBlock","NoPeers","NotConnected","Peer","PeerBloomDisabled","Time","Timeout","add_tx","address","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone","clone_into","clone_into","connect","connect_proxy","default","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","drop","drop","drop","drop","drop","drop","eq","eq","estimate_fee","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from_config","get_block_hash","get_capabilities","get_height","get_mempool","get_network","get_tx","get_tx","get_version","has_tx","init","init","init","init","init","init","into","into","into","into","into","into","is_connected","iter_txs","network","new","new","peers","provide","recv","send","serialize","serialize","skip_blocks","socks5","socks5_credentials","storage_dir","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","wallet_setup","ElectrumBlockchain","ElectrumBlockchainConfig","borrow","borrow","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref","deref_mut","deref_mut","deserialize","drop","drop","eq","estimate_fee","fmt","from","from","from","from_config","get_block_hash","get_capabilities","get_height","get_tx","init","init","into","into","retry","serialize","socks5","stop_gap","timeout","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","url","validate_domain","vzip","vzip","wallet_setup","BitcoinEncoding","EsploraBlockchain","EsploraBlockchainConfig","EsploraError","HeaderHashNotFound","HeaderHeightNotFound","Hex","HttpResponse","Io","NoHeader","Parsing","TransactionNotFound","Ureq","UreqTransport","base_url","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone_into","concurrency","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deserialize","drop","drop","drop","eq","estimate_fee","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from_client","from_config","get_block_hash","get_capabilities","get_height","get_tx","init","init","init","into","into","into","new","new","provide","proxy","serialize","stop_gap","timeout","to_owned","to_string","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","vzip","vzip","vzip","wallet_setup","with_concurrency","Auth","Cookie","None","RpcBlockchain","RpcBlockchainFactory","RpcConfig","RpcSyncParams","UserPass","auth","auth","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","broadcast","build","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","default","default_skip_blocks","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","eq","eq","eq","estimate_fee","fmt","fmt","fmt","fmt","fmt","force_start_time","from","from","from","from","from","from_config","get_block_hash","get_capabilities","get_hash","get_height","get_tx","hash","init","init","init","init","init","into","into","into","into","into","network","network","partial_cmp","poll_rate_sec","serialize","serialize","serialize","start_script_count","start_time","sync_params","sync_params","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","url","url","vzip","vzip","vzip","vzip","vzip","wallet_name","wallet_name_prefix","wallet_setup","file","password","username","AnyDatabase","AnyDatabaseConfig","Batch","BatchDatabase","BatchOperations","Config","ConfigurableDatabase","Database","MemoryDatabase","SqliteDatabase","SyncTime","any","begin_batch","begin_batch","block_time","borrow","borrow","borrow_mut","borrow_mut","check_descriptor_checksum","check_descriptor_checksum","clone","clone_into","commit_batch","commit_batch","connection","del_last_index","del_last_index","del_path_from_script_pubkey","del_path_from_script_pubkey","del_raw_tx","del_raw_tx","del_script_pubkey_from_path","del_script_pubkey_from_path","del_sync_time","del_sync_time","del_tx","del_tx","del_utxo","del_utxo","deref","deref","deref_mut","deref_mut","deserialize","drop","drop","eq","fmt","fmt","from","from","from_config","from_config","get_last_index","get_last_index","get_path_from_script_pubkey","get_path_from_script_pubkey","get_raw_tx","get_raw_tx","get_script_pubkey_from_path","get_script_pubkey_from_path","get_sync_time","get_sync_time","get_tx","get_tx","get_utxo","get_utxo","increment_last_index","increment_last_index","init","init","into","into","iter_raw_txs","iter_raw_txs","iter_script_pubkeys","iter_script_pubkeys","iter_txs","iter_txs","iter_utxos","iter_utxos","memory","new","path","serialize","set_last_index","set_last_index","set_raw_tx","set_raw_tx","set_script_pubkey","set_script_pubkey","set_sync_time","set_sync_time","set_tx","set_tx","set_utxo","set_utxo","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","AnyBatch","AnyDatabase","AnyDatabaseConfig","Memory","Memory","Memory","Sled","Sled","Sled","SledDbConfiguration","Sqlite","Sqlite","Sqlite","SqliteDbConfiguration","begin_batch","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_descriptor_checksum","commit_batch","del_last_index","del_last_index","del_path_from_script_pubkey","del_path_from_script_pubkey","del_raw_tx","del_raw_tx","del_script_pubkey_from_path","del_script_pubkey_from_path","del_sync_time","del_sync_time","del_tx","del_tx","del_utxo","del_utxo","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_config","get_last_index","get_path_from_script_pubkey","get_raw_tx","get_script_pubkey_from_path","get_sync_time","get_tx","get_utxo","increment_last_index","init","init","init","init","init","into","into","into","into","into","iter_raw_txs","iter_script_pubkeys","iter_txs","iter_utxos","path","path","serialize","serialize","serialize","set_last_index","set_last_index","set_raw_tx","set_raw_tx","set_script_pubkey","set_script_pubkey","set_sync_time","set_sync_time","set_tx","set_tx","set_utxo","set_utxo","tree_name","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","MemoryDatabase","begin_batch","borrow","borrow_mut","check_descriptor_checksum","commit_batch","default","del_last_index","del_path_from_script_pubkey","del_raw_tx","del_script_pubkey_from_path","del_sync_time","del_tx","del_utxo","deref","deref_mut","drop","fmt","from","from_config","get_last_index","get_path_from_script_pubkey","get_raw_tx","get_script_pubkey_from_path","get_sync_time","get_tx","get_utxo","increment_last_index","init","into","iter_raw_txs","iter_script_pubkeys","iter_txs","iter_utxos","new","set_last_index","set_raw_tx","set_script_pubkey","set_sync_time","set_tx","set_utxo","try_from","try_into","type_id","vzip","Bare","DerivedDescriptor","Descriptor","DescriptorError","DescriptorPublicKey","DescriptorXKey","ExtendedDescriptor","ExtractPolicy","Hardened","HdKeyPaths","IntoWalletDescriptor","Key","KeyMap","Legacy","Miniscript","None","Pkh","Policy","ScriptContext","Segwitv0","Sh","Single","TapKeyOrigins","Tr","Unhardened","Wildcard","Wpkh","Wsh","XPub","address","as_enum","as_enum","as_inner","at_derivation_index","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","calc_checksum","check_global_consensus_validity","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","cmp","contains_raw_pkh","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","derivation_path","derive","derived_descriptor","derived_descriptor","desc_type","deserialize","deserialize","drop","drop","drop","drop","drop","drop","encode","eq","eq","eq","eq","eq","eq","error","explicit_script","ext","ext_check","extract_policy","extract_policy","extract_policy","find_derivation_index_for_spk","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","for_each_key","from","from","from","from","from","from","from","from","from","from","from","from","from_ast","from_str","from_str","from_str_ext","from_str_insane","from_tree","from_tree","get_hash","get_hash","get_hash","get_hash","get_hash","get_hash","get_nth_child","get_nth_pk","get_satisfaction","get_satisfaction_mall","has_mixed_timelocks","has_repeated_keys","has_wildcard","hash","hash","hash","hash","hash","hash","init","init","init","init","init","init","into","into","into","into","into","into","into_inner","into_wallet_descriptor","into_wallet_descriptor","is_deriveable","is_non_malleable","iter","iter_pk","lift","lift","lift_check","matches","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","name_str","name_str","name_str","new_bare","new_pk","new_pkh","new_sh","new_sh_sortedmulti","new_sh_with_wpkh","new_sh_with_wsh","new_sh_wpkh","new_sh_wsh","new_sh_wsh_sortedmulti","new_tr","new_wpkh","new_wsh","new_wsh_sortedmulti","node","origin","other_top_level_checks","parse","parse_descriptor","parse_insane","parse_with_ext","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pk_len","pk_len","policy","requires_sig","sanity_check","sanity_check","satisfy","satisfy","satisfy_malleable","script_code","script_pubkey","script_size","serialize","serialize","sig_type","sig_type","sig_type","template","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string_with_secret","top_level_checks","top_level_type_check","translate_pk","translate_pk","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","vzip","vzip","wildcard","within_resource_limits","xkey","calc_checksum","calc_checksum_bytes","get_checksum","get_checksum_bytes","Base58","Bip32","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","Pk","Policy","borrow","borrow_mut","deref","deref_mut","drop","fmt","fmt","from","from","from","from","from","from","from","from","init","into","provide","to_string","try_from","try_into","type_id","vzip","AbsoluteTimelock","AddOnLeaf","AddOnPartialComplete","BuildSatisfaction","Complete","Condition","ConditionMap","EcdsaSignature","Fingerprint","FoldedConditionMap","Hash160Preimage","Hash256Preimage","IncompatibleConditions","IndexOutOfRange","MixedTimelockUnits","Multisig","None","None","NotEnoughItemsSelected","Partial","PartialComplete","PkOrF","Policy","PolicyError","Psbt","PsbtTimelocks","Pubkey","RelativeTimelock","Ripemd160Preimage","Satisfaction","SatisfiableItem","SchnorrSignature","Sha256Preimage","Thresh","XOnlyPubkey","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","contribution","csv","default","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","get_condition","get_hash","get_hash","hash","hash","id","id","init","init","init","init","init","init","init","into","into","into","into","into","into","into","is_leaf","is_leaf","is_null","item","partial_cmp","provide","requires_path","satisfaction","serialize","serialize","serialize","serialize","serialize","timelock","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","current_height","input_max_height","psbt","condition","conditions","conditions","items","items","m","m","n","n","sorted","sorted","hash","hash","hash","hash","items","keys","threshold","threshold","value","value","Bip44","Bip44Public","Bip49","Bip49Public","Bip84","Bip84Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2Wpkh","P2Wpkh_P2Sh","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","build","build","build","build","build","build","build","build","build","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","drop","drop","from","from","from","from","from","from","from","from","from","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","Entropy","Error","ExtScriptContext","ExtendedKey","FullKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","Key","KeyError","KeyMap","Legacy","Message","Miniscript","Options","Private","PrivateKeyGenerateOptions","Public","ScriptContext","ScriptContextEnum","Segwitv0","Single","Single","SinglePriv","SinglePub","SinglePubKey","SortedMultiVec","Tap","ValidNetworks","XOnly","XPrv","XPub","any_network","as_enum","at_derivation_index","bip39","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_global_consensus_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_policy_validity","check_local_validity","check_terminal_non_malleable","check_witness","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","compressed","default","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","derive","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","encode","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_public","from_secret","from_str","from_str","from_tree","full_derivation_path","generate","generate_default","generate_with_entropy","generate_with_entropy_default","get_hash","get_hash","get_hash","get_hash","has_secret","has_wildcard","hash","hash","hash","hash","init","init","init","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into","into","into","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_extended_key","into_key","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_segwit_v0","is_segwit_v0","is_taproot","is_taproot","is_uncompressed","is_x_only_key","k","key","key","lift","mainnet_network","master_fingerprint","max_satisfaction_size","max_satisfaction_size","max_satisfaction_witness_elements","merge_networks","name_str","new","origin","origin","other_top_level_checks","override_valid_networks","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pks","provide","sanity_check","satisfy","script_size","sig_type","sorted_node","test_networks","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_public","to_string","to_string","to_string","to_string","top_level_checks","top_level_type_check","translate_pk","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","AmbiguousLanguages","BadEntropyBitCount","BadWordCount","English","Error","InvalidChecksum","Language","Mnemonic","MnemonicWithPassphrase","UnknownWord","WordCount","Words12","Words15","Words18","Words21","Words24","all","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone_into","clone_into","clone_into","cmp","cmp","default","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","drop","drop","drop","drop","eq","eq","eq","find_word","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from_entropy","from_entropy_in","from_str","generate_in_with","generate_with_entropy","get_hash","get_hash","hash","hash","init","init","init","init","into","into","into","into","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","language","language_of","parse","parse_in","parse_in_normalized","parse_normalized","partial_cmp","partial_cmp","provide","serialize","to_entropy","to_entropy_array","to_owned","to_owned","to_owned","to_seed","to_seed_normalized","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","word_count","word_iter","word_list","words_by_prefix","PsbtUtils","fee_amount","fee_rate","get_utxo_for","AddressIndex","AddressInfo","IsDust","LastUnused","New","Peek","Reset","SyncOptions","Wallet","add_signer","address","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build_fee_bump","build_tx","coin_selection","database","default","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","descriptor_checksum","drop","drop","drop","drop","ensure_addresses_cached","eq","export","finalize_psbt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","get_address","get_balance","get_descriptor_for_keychain","get_funded_wallet","get_internal_address","get_psbt_input","get_signers","get_tx","get_utxo","hardwaresigner","index","init","init","init","init","into","into","into","into","is_dust","is_mine","keychain","list_transactions","list_unspent","network","new","new_offline","policies","progress","public_descriptor","secp_ctx","sign","signer","sync","time","to_string","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","tx_builder","type_id","type_id","type_id","type_id","verify","vzip","vzip","vzip","vzip","wallet_name_from_descriptor","BranchAndBoundCoinSelection","Change","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","Excess","LargestFirstCoinSelection","NoChange","OldestFirstCoinSelection","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","coin_select","coin_select","coin_select","coin_select","decide_change","default","default","default","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","excess","fee_amount","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","init","init","init","init","init","into","into","into","into","into","local_selected_amount","new","selected","selected_amount","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","amount","change_fee","dust_threshold","fee","remaining_amount","FullyNodedExport","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","deref","deref_mut","descriptor","deserialize","drop","export_wallet","fmt","from","from_str","init","into","label","serialize","to_string","try_from","try_into","type_id","vzip","HWISigner","borrow","borrow_mut","deref","deref_mut","drop","fmt","from","from_device","id","init","into","sign_transaction","try_from","try_into","type_id","vzip","All","Dummy","Exclude","Fingerprint","HWIError","Include","InputIndexOutOfRange","InputSigner","InvalidKey","InvalidNonWitnessUtxo","InvalidSighash","Legacy","MissingHdKeypath","MissingKey","MissingNonWitnessUtxo","MissingWitnessScript","MissingWitnessUtxo","NonStandardSighash","None","PkHash","Segwitv0","SighashError","SignOptions","SignerCommon","SignerContext","SignerError","SignerId","SignerOrdering","SignerWrapper","SignersContainer","Tap","TapLeavesOptions","TransactionSigner","UserCanceled","add_external","allow_all_sighashes","allow_grinding","as_key_map","assume_height","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","default","default","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","descriptor_secret_key","descriptor_secret_key","descriptor_secret_key","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","find","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","get_hash","hash","id","id","id","ids","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","new","new","partial_cmp","partial_cmp","provide","remove","remove_partial_sigs","sign_input","sign_input","sign_input","sign_transaction","sign_transaction","sign_with_tap_internal_key","signers","tap_leaves_options","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","trust_witness_utxo","try_finalize","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","is_internal_key","get_timestamp","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","Untouched","add_data","add_foreign_utxo","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_dust","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_policy","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","coin_selection","current_height","default","default","default","default","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","do_not_spend_change","drain_to","drain_wallet","drop","drop","drop","drop","drop","enable_rbf","enable_rbf_with_sequence","eq","eq","fee_absolute","fee_rate","finish","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","get_hash","get_hash","hash","hash","include_output_redeem_witness_script","init","init","init","init","init","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","set_recipients","sighash","sort_tx","to_owned","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","unspendable","version","vzip","vzip","vzip","vzip","vzip","Consensus","Global","InvalidInput","MissingInputTx","VerifyError","borrow","borrow_mut","deref","deref_mut","drop","fmt","fmt","from","from","from","init","into","provide","to_string","try_from","try_into","type_id","verify_tx","vzip"],"q":["bdk","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Error","","","","","","bdk::Utxo","","bdk::blockchain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::any","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::compact_filters","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::electrum","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::esplora","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::rpc","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::rpc::Auth","","","bdk::database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::database::any","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::database::memory","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::checksum","","","","bdk::descriptor::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy::BuildSatisfaction","","","bdk::descriptor::policy::Satisfaction","","","","","","","","","","","bdk::descriptor::policy::SatisfiableItem","","","","","","","","","","bdk::descriptor::template","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys::bip39","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::psbt","","","","bdk::wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::coin_selection::Excess","","","","","bdk::wallet::export","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::hardwaresigner","","","","","","","","","","","","","","","","","bdk::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer::SignerContext","bdk::wallet::time","bdk::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::verify","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Balance differentiated in various categories","BIP32 error","Block height and timestamp of a block","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","Descriptor checksum mismatch","Compact filters client error)","DEPRECATED: Confirmation time of a transaction","Error related to the parsing and usage of descriptors","Electrum client error","Encoding error","Errors that can be thrown by the Wallet","Esplora client error","External","Fee rate","When bumping a tx the fee rate requested is lower than …","Node doesn’t have data to estimate a fee rate","When bumping a tx the absolute fee requested is lower than …","A UTXO owned by another wallet.","Generic error","","Hex decoding error","Wallet’s UTXO set is not enough to cover recipient’s …","Internal, usually used for change outputs","Invalid network","Requested outpoint doesn’t exist in the tx (vout greater …","Error while extracting and manipulating policies","Progress value must be between 0.0 (included) and 100.0 …","Wrong number of bytes found when trying to convert to u32","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Error serializing or deserializing JSON data","Error while working with keys","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","Miniscript error","Miniscript PSBT error","crate::blockchain::WalletSync sync attempt failed due to …","In order to use the TxBuilder::add_global_xpubs option …","Cannot build a tx without recipients","manually_selected_only option is selected but no utxo has …","Output created is under the dust limit, 546 satoshis","Progress update error (maybe the channel has been closed)","Partially signed bitcoin transaction error","Partially signed bitcoin transaction parse error","Rpc client error","Rusqlite client error","This error is thrown when trying to convert Bare and …","A secp256k1 error","","Signing error","Sled database error","Spending policy is not compatible with this KeychainKind","","Happens when trying to bump a transaction that is already …","A wallet transaction","Thrown when a tx is not found in the internal database","","Happens when trying to spend an UTXO that is not in the …","An unspent transaction output (UTXO).","Trait implemented by types that can be used to measure …","Transaction verification error","","A Utxo with its satisfaction_weight.","","Return KeychainKind as a byte","","Return the value as satoshi/vbyte","","Blockchain backends","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","If the transaction is confirmed, contains height and Unix …","Confirmed and immediately spendable balance","Database types","","","","Create a new FeeRate with the default min relay fee value","","","","","","","","","","","","","","","","","","","Descriptors","Macro to write full descriptors with code","","","","","","","","","","","","","","","","","","","","","","","Fee value (sats) if confirmed. The availability of the fee …","Calculate absolute fee in Satoshis using size in virtual …","Calculate absolute fee in Satoshis using size in weight …","","","","","","","","","","","","Macro to write descriptor fragments with code","","","","Returns the argument unchanged.","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Calculate fee rate from fee and vbytes.","Calculate fee rate from fee and weight units (wu).","","","Get sum of trusted_pending and confirmed coins","Get the whole balance visible to the wallet","","","confirmation block height","All coinbase outputs not yet matured","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Whether this UTXO is spent or not","Type of keychain","Key formats","Returns Some BlockTime if both height and timestamp are …","Get the location of the UTXO","Reference to a transaction output","","","","","Additional functions on the rust-bitcoin …","Received value (sats) Sum of owned outputs of this …","The weight of the witness data and scriptSig expressed in …","Sent value (sats) Sum of owned inputs of this transaction.","","","","","","","","","","confirmation block timestamp","","","","","","","","","","","Optional transaction","Unconfirmed UTXOs generated by a wallet tx","","","","","","","","","","","","","","","","","","","Transaction id","Get the TxOut of the UTXO","Transaction output","","","","","","","","","","Unconfirmed UTXOs received from an external wallet","The UTXO","Convert weight units to virtual bytes.","Get the version of BDK at runtime","","","","","","","","","","Wallet","","Sats available for spending","found network, for example the network of the bitcoin node","Sats needed for some transaction","requested network, for example what is given as bdk-cli …","Required fee rate (satoshi/vbyte)","Required fee absolute value (satoshi)","The location of the output.","The information about the input we require to add it to a …","Can compute accurate fees for the transactions found …","","","Trait that defines the actions that must be supported by a …","Trait for a factory of blockchains that share the …","Capabilities that can be supported by a Blockchain backend","","Type that contains the configuration","Trait for Blockchain types that can be created given a …","","","Structure that implements the logic to sync with Esplora","Can recover the full history of a wallet and not only the …","Can fetch any historical transaction given its txid","Trait for getting block hash by block height","Trait for getting the current height of the blockchain.","Trait for getting a transaction by txid","The type returned when building a blockchain from this …","Type that implements Progress and logs at level INFO every …","Type that implements Progress and drops every update …","Trait for types that can receive and process progress …","Data sent with a progress update over a channel","","","Trait for blockchains that don’t contain any state","Trait for blockchains that can sync by updating the …","Runtime-checked blockchain types","","","","","","","Broadcast a transaction","Build a new blockchain for the given descriptor wallet_name","Build a new blockchain for a given wallet","","","","","","","Compact Filters","","","","","","","","","","","","Electrum","","Esplora","Estimate the fee rate required to confirm a transaction in …","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Create a new instance given a configuration","fetch block hash given its height","Return the set of Capability supported by this backend","","Return the current height","Fetch a transaction given its txid","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Create a new instance of LogProgress","Create a new instance of NoopProgress","Shortcut to create a channel (pair of Sender and Receiver) …","Rpc Blockchain","Use BlockchainFactory::build_for_wallet to get a …","","","","","","","","","","","","","Send a new progress update","","","","","","Setup the backend and populate the internal database for …","If not overridden, it defaults to calling …","Type that can contain any of the Blockchain types defined …","Type that can contain any of the blockchain configurations …","Compact filters client","Compact filters client","Electrum client","Electrum client","Esplora client","Esplora client","RPC client","RPC client configuration","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","","","","","","","","","Returns the argument unchanged.","","","","","","","","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","Invalid BIP158 filter","Data to connect to a Bitcoin P2P peer","Block hash at specified height not found","Structure implementing the required blockchain traits","Configuration for a CompactFiltersBlockchain","An error that can occur during sync with a …","The data stored in the block filters storage are corrupted","Internal database error","Wrapper for crate::error::Error","The compact filter returned is invalid","The compact filter headers returned are invalid","The headers returned are invalid","A peer sent an invalid or unexpected response","Internal I/O error","Container for unconfirmed, but valid Bitcoin transactions","The peer is missing a block in the valid chain","No peers have been specified","A peer is not connected","A Bitcoin peer","The peer doesn’t advertise the BLOOM service flag","Internal system time error","A peer took too long to reply to one of our messages","Add a transaction to the mempool","Peer address such as 127.0.0.1:18333","","","","","","","","","","","","","","","","","","Connect to a peer over a plaintext TCP connection","Connect to a peer through a SOCKS5 proxy, optionally by …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","","","","","","","","Return the mempool used by this peer","Return the Bitcoin Network in use","Look-up a transaction in the mempool given an Inventory …","","Return the VersionMessage sent by the peer","Return whether or not the mempool contains a transaction …","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Return whether or not the peer is still connected","Return the list of transactions contained in the mempool","Network used","Create a new empty mempool","Construct a new instance given a list of peers, a path to …","List of peers to try to connect to for asking headers and …","","Waits for a specific incoming Bitcoin message, optionally …","Send a raw Bitcoin message to the peer","","","Optionally skip initial skip_blocks blocks (default: 0)","Optional socks5 proxy","Optional socks5 proxy credentials","Storage dir to save partially downloaded headers and full …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Wrapper over an Electrum Client that implements the …","Configuration for an ElectrumBlockchain","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","","","","","","","","Calls U::from(self).","Calls U::from(self).","Request retry count","","URL of the socks5 proxy server or a Tor service","Stop searching addresses for transactions after finding an …","Request timeout (seconds)","","","","","","","","URL of the Electrum server (such as ElectrumX, Esplora, …","Validate the domain when using SSL","","","","Invalid Bitcoin data returned","Structure that implements the logic to sync with Esplora","Configuration for an EsploraBlockchain","Errors that can happen during a sync with Esplora","Header hash not found","Header height not found","Invalid Hex data returned","HTTP response error","IO error during ureq response read","No header found in ureq response","Invalid number returned","Transaction not found","Error during ureq HTTP request","Transport error during the ureq HTTP call","Base URL of the esplora service","","","","","","","","","","Number of parallel requests sent to the esplora service …","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Build a new instance given a client","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Create a new instance of the client from a base URL and …","create a config with default values given the base url and …","","Optional URL of the proxy to use to make requests to the …","","Stop searching addresses for transactions after finding an …","Socket timeout.","","","","","","","","","","","","","","","","Set the number of parallel requests the client can make.","This struct is equivalent to bitcoincore_rpc::Auth but it …","Authentication with a cookie file","None authentication","The main struct for RPC backend implementing the …","Factory of RpcBlockchain instances, implements …","RpcBlockchain configuration options","Sync parameters for Bitcoin Core RPC.","Authentication with username and password, usually …","The bitcoin node authentication mechanism","The bitcoin node authentication mechanism","","","","","","","","","","","","","","","","","","","","","","","Default number of blocks to skip which will be inherited …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Forces every sync to use start_time as import timestamp.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns RpcBlockchain backend creating an RPC client to a …","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The network we are using (it will be checked the bitcoin …","The network we are using (it will be checked the bitcoin …","","RPC poll rate (in seconds) to get state updates.","","","","The minimum number of scripts to scan for on initial sync.","Time in unix seconds in which initial sync will start …","Sync parameters","Sync parameters","","","","","","","","","","","","","","","","","","","","The bitcoin node url","The bitcoin node url","","","","","","The wallet name in the bitcoin node, consider using …","The optional prefix used to build the full wallet name for …","","Cookie file","Password","Username","","","Container for the operations","Trait for a database that supports batch operations","Trait for operations that can be batched","Type that contains the configuration","Trait for Database types that can be created given a …","Trait for reading data from a database","","Sqlite database stored on filesystem","Blockchain state at the time of syncing","Runtime-checked database types","Create a new batch container","","Block timestamp and height at the time of sync","","","","","Read and checks the descriptor checksum for a given …","","","","Consume and apply a batch of operations","","A rusqlite connection object to the sqlite database","Delete the last derivation index for a keychain.","","Delete the data related to a specific script_pubkey, …","","Delete a raw transaction given its Txid","","Delete a script_pubkey given the keychain and its child …","","Reset the sync time to None","","Delete the metadata of a transaction and optionally the …","","Delete a LocalUtxo given its OutPoint","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Create a new instance given a configuration","","Return the last derivation index for a keychain.","","Fetch the keychain and child number of a given …","","Fetch a raw transaction given its Txid","","Fetch a script_pubkey given the child number of a keychain.","","Return the sync time, if present","","Fetch the transaction metadata and optionally also the raw …","","Fetch a LocalUtxo given its OutPoint","","Increment the last derivation index for a keychain and …","","","","Calls U::from(self).","Calls U::from(self).","Return the list of raw transactions","","Return the list of script_pubkeys","","Return the list of transactions metadata","","Return the list of LocalUtxos","","In-memory ephemeral database","Instantiate a new SqliteDatabase instance by creating a …","Path on the local filesystem to store the sqlite file","","Store the last derivation index for a given keychain.","","Store a raw transaction","","Store a script_pubkey along with its keychain and child …","","Store the sync time","","Store the metadata of a transaction","","Store a LocalUtxo","","","","","","","","","","","Type that contains any of the BatchDatabase::Batch types …","Type that can contain any of the Database types defined by …","Type that can contain any of the database configurations …","In-memory ephemeral database","In-memory ephemeral database","Memory database has no config","Simple key-value embedded database based on sled","Simple key-value embedded database based on sled","Simple key-value embedded database based on sled","Configuration type for a sled::Tree database","Sqlite embedded database using rusqlite","Sqlite embedded database using rusqlite","Sqlite embedded database using rusqlite","Configuration type for a sqlite::SqliteDatabase database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","","","","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","Main directory of the db","Main directory of the db","","","","","","","","","","","","","","","","Name of the database tree, a separated namespace for the …","","","","","","","","","","","","","","","","","","","","","In-memory ephemeral database","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","","","","","","","","","","","Calls U::from(self).","","","","","Create a new empty database","","","","","","","","","","","A raw scriptpubkey (including pay-to-pubkey) under Legacy …","Alias for a Descriptor that contains extended derived keys","Script descriptor","","The descriptor pubkey, either a single pubkey or an xpub.","An extended key with origin, derivation path, and wildcard.","Alias for a Descriptor that can contain extended keys …","Trait implemented on Descriptors to add a method to …","Unhardened wildcard, e.g. *h","Alias for the type of maps that represent derivation paths …","Trait for types which can be converted into an …","The consensus key associated with the type. Must be a …","Alias type for a map of public key to secret key","Legacy ScriptContext To be used as P2SH scripts For …","Top-level script AST type","No wildcard","Pay-to-PubKey-Hash","","The ScriptContext for Miniscript. Additional type …","Segwitv0 ScriptContext","Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)","Single public key.","Alias for the type of maps that represent taproot key …","Pay-to-Taproot","Unhardened wildcard, e.g. *","Whether a descriptor has a wildcard in it","Pay-to-Witness-PubKey-Hash","Pay-to-Witness-ScriptHash with Segwitv0 context","Extended public key (xpub).","Computes the Bitcoin address of the descriptor, if one …","","","Get a reference to the inner AstElem representing the root …","Replaces all wildcards (i.e. /*) in the descriptor with a …","","","","","","","","","","","","","Enumerates all child nodes of the current AST node (self) …","","Depending on script Context, some of the Terminals might …","","","Depending on script Context, some of the script resource …","","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","","","Policy rules at the Miniscript satisfaction time. It is …","","","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","","","Check whether the given satisfaction is valid under the …","","","Descriptor checksum","","","","","","","","","","","","","","","","","","","Whether the given miniscript contains a raw pkh fragment","","","","","","","","","","","","","The derivation path","Deprecated name for [at_derivation_index].","Convert all the public keys in the descriptor to …","Convert all the public keys in the descriptor to …","Get the DescriptorType of Descriptor","","","","","","","","","Encode as a Bitcoin script","","","","","","","Descriptor errors","Computes the the underlying script before any hashing is …","Additional information helpful for extra analysis.","Check whether the miniscript follows the given Extra …","Extract the spending policy","","","Utility method for deriving the descriptor at each index …","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Add type information(Type and Extdata) to Miniscript based …","","Parse a Miniscript from string and perform sanity checks …","Attempt to parse an Miniscripts that don’t follow the …","Attempt to parse an insane(scripts don’t clear sanity …","Parse an expression tree into a descriptor.","Parse an expression tree into a Miniscript. As a general …","","","","","","","Returns child node with given index, if any","Returns Option::Some with cloned n’th public key from …","Returns satisfying non-malleable witness and scriptSig to …","Returns a possilbly mallable satisfying non-malleable …","Whether the miniscript contains a combination of timelocks","Whether the miniscript has repeated Pk or Pkh","Whether or not the descriptor has any wildcards i.e. /*.","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Extracts the AstElem representing the root of the …","Convert to wallet descriptor","","Whether or not the descriptor has any wildcards","Whether the miniscript is malleable","Creates a new Iter iterator that will iterate over all …","Creates a new PkIter iterator that will iterate over all …","","","Lifting corresponds conversion of miniscript into Policy […","Compares this key with a keysource and returns the …","Depending on script context, the size of a satifaction …","","","Maximum size, in bytes, of a satisfying witness. For …","Computes an upper bound on the weight of a satisfying …","Maximum number of witness elements used to satisfy the …","Local helper function to display error messages with …","","","Create a new bare descriptor from witness script Errors …","Create a new pk descriptor","Create a new PkH descriptor","Create a new sh for a given redeem script Errors when …","Create a new sh sortedmulti descriptor with threshold k …","Create a new sh wrapper for the given wpkh descriptor","Create a new sh wrapper for the given wsh descriptor","Create a new sh wrapped wpkh from Pk. Errors when …","Create a new sh wrapped wsh descriptor with witness script …","Create a new sh wrapped wsh sortedmulti descriptor from …","Create new tr descriptor Errors when miniscript exceeds …","Create a new Wpkh descriptor Will return Err if …","Create a new wsh descriptor from witness script Errors …","Create a new wsh sorted multi descriptor Errors when …","A node in the Abstract Syntax Tree(","Origin information","Other top level checks that are context specific","Attempt to parse a Script into Miniscript representation.","Parse a descriptor that may contain secret keys","Attempt to parse an insane(scripts don’t clear sanity …","Attempt to parse an miniscript with extra features that …","","","","","","","Get the len of public key when serialized based on context …","","","Descriptor policy","Whether all spend paths of miniscript require a signature","Checks whether the descriptor is safe.","Check whether the underlying Miniscript is safe under the …","Attempts to produce a non-malleable satisfying witness and …","Attempt to produce non-malleable satisfying witness for the","Attempt to produce a malleable satisfying witness for the …","Computes the scriptCode of a transaction output.","Computes the scriptpubkey of the descriptor.","Size, in bytes of the script-pubkey. If this Miniscript is …","","","The type of signature required for satisfaction","","","Descriptor templates","","","","","","","","","Serialize a descriptor to string with its secret keys","Check top level consensus rules.","Check whether the top-level is type B","Converts a descriptor using abstract keys to one using …","Translates a struct from one generic to another where the …","","","","","","","","","","","","","The correctness and malleability type information for the …","","","","","","","Computes the scriptSig that will be in place for an …","","","","","","","Whether the descriptor is wildcard","Whether the miniscript can exceed the resource …","The extended key","Compute the checksum of a descriptor, excludes any …","Compute the checksum bytes of a descriptor, excludes any …","Compute the checksum of a descriptor","Compute the checksum bytes of a descriptor","Error during base58 decoding","BIP32 error","Errors related to the parsing and usage of descriptors","The descriptor contains hardened derivation steps on …","Hex decoding error","Invalid byte found in the descriptor checksum","The provided descriptor doesn’t match its checksum","Invalid HD Key path, such as having a wildcard but a …","Error thrown while working with keys","Miniscript error","Key-related error","Error while extracting and manipulating policies","","","","","","","","","","","","Returns the argument unchanged.","","","","","Calls U::from(self).","","","","","","","Absolute timeclock timestamp","Can not add to an item that is Satisfaction::None or …","Can not add to an item that is …","Options to build the satisfaction field in the policy","Can satisfy the policy item","An extra condition that must be satisfied but that is out …","Type for a map of sets of Condition items keyed by each set…","ECDSA Signature for a raw public key","An extended key fingerprint","Type for a map of folded sets of Condition items keyed by …","SHA256 then RIPEMD160 preimage hash","Double SHA256 preimage hash","Incompatible conditions (not currently used)","Index out of range for an item to satisfy a …","Can not merge CSV or timelock values unless both are less …","Multi-signature public keys with threshold count","Cannot satisfy or contribute to the policy item","Don’t generate satisfaction field","Not enough items are selected to satisfy a …","Only a partial satisfaction of some kind of threshold …","Can reach the threshold of some kind of threshold policy","A unique identifier for a key","Descriptor spending policy","Errors that can happen while extracting and manipulating …","Analyze the given PSBT to check for existing signatures","Like Psbt variant and also check for expired timelocks","A legacy public key","Relative timelock locktime","RIPEMD160 preimage hash","Represent if and how much a policy item is satisfied by …","An item that needs to be satisfied","Schnorr Signature for a raw public key","SHA256 preimage hash","Threshold items with threshold count","A x-only public key","","","","","","","","","","","","","","","","","","","","","","","","","","","How the wallet’s descriptor can satisfy this policy node","Optional CheckSequenceVerify condition","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return the conditions that are set by the spending policy …","","","","","Returns a unique id for the SatisfiableItem","Identifier for this policy node","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns whether the SatisfiableItem is a leaf item","Returns whether the Satisfaction is a leaf item","Returns true if there are no extra conditions to verify","Type of this policy node","","","Return whether or not a specific path in the policy tree …","How much a given PSBT already satisfies this policy node …","","","","","","Optional timelock condition","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Current blockchain height","The highest confirmation height between the inputs CSV …","Given PSBT","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","The items that can be satisfied by the descriptor or are …","The items that can be satisfied by the descriptor","Threshold","Threshold","Total number of items","Total number of items","Whether the items are sorted in lexicographic order (used …","Whether the items are sorted in lexicographic order (used …","The digest value","The digest value","The digest value","The digest value","The policy items","The raw public key or extended key fingerprint","The required threshold count","The required threshold count","The timelock value","The timelock value","BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/*)","BIP44 public template. Expands to pkh(key/{0,1}/*)","BIP49 template. Expands to …","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))","BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/*)","BIP84 public template. Expands to wpkh(key/{0,1}/*)","Trait for descriptor templates that can be built into a …","Type alias for the return type of DescriptorTemplate, …","P2PKH template. Expands to a descriptor pkh(key)","P2WPKH template. Expands to a descriptor wpkh(key)","P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))","","","","","","","","","","","","","","","","","","","Build the complete descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","BIP32 error","Trait for keys that can be derived.","Container for public or secret keys","The descriptor pubkey, either a single pubkey or an xpub.","The descriptor secret key, either a single private key or …","Type specifying the amount of entropy required e.g. [u8;32]","Returned error in case of failure","Trait that adds extra useful methods to ScriptContexts","Enum for extended keys that can be either xprv or xpub","A bitcoin public key (compressed or uncompressed).","Trait that allows generating a key with the default options","Trait for keys that can be generated","Output of a GeneratableKey key generation","Trait for objects that can be turned into a public or …","The key has an invalid checksum","The key is not valid for the given network","The key cannot exist in the given script context","The consensus key associated with the type. Must be a …","Errors thrown while working with keys","Alias type for a map of public key to secret key","Legacy scripts","Custom error message","Miniscript error","Extra options required by the generate_with_entropy","A private extended key, aka an xprv","Options for generating a PrivateKey","A public extended key, aka an xpub","The ScriptContext for Miniscript. Additional type …","Enum representation of the known valid ScriptContexts","Segwitv0 scripts","Single public key.","Single private key.","A descriptor bitcoin::PrivateKey with optional origin …","A descriptor SinglePubKey with optional origin information.","Single public key without any origin or range information.","Contents of a “sortedmulti” descriptor","Taproot scripts","Set of valid networks for a key","An xonly public key.","Extended private key (xpriv).","Extended public key (xpub).","Create a set containing mainnet, testnet, signet, and …","Returns the ScriptContext as a ScriptContextEnum","Replaces any wildcard (i.e. /*) in the key with a …","BIP-0039","","","","","","","","","","","","","","","","","","","","","","","","","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the script resource …","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","Policy rules at the Miniscript satisfaction time. It is …","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","Check whether the given satisfaction is valid under the …","","","","","","","","","","","","","","","","","","","Whether the generated key should be “compressed” or not","","","","","","","","","","","","","","","","","","","","","","","","","","","Deprecated name of [at_derivation_index].","","","","","","","","","","","","","Encode as a Bitcoin script","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Create an instance given a public key and a set of valid …","Create an instance given a secret key and a set of valid …","","","Parse an expression tree into a SortedMultiVec","Full path, from the master key","Generate a key given the options with a random entropy","Generate a key with the default options and a random …","Generate a key given the extra options and the entropy","Generate a key with the default options and a given entropy","","","","","Return whether or not the key contains the private data","Whether or not the key has a wildcard","","","","","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Turn the key into a DescriptorKey within the requested …","Consume self and turn it into a DescriptorKey by adding …","","","","","","Consume self and turn it into an ExtendedKey","","","Consumes self and returns the key","Transform the ExtendedKey into an ExtendedPrivKey for the …","Transform the ExtendedKey into an ExtendedPubKey for the …","Whether or not the key has a wildcard","Returns whether the script context is Legacy","Returns whether the script context is …","Returns whether the script context is Segwitv0","Returns whether the script context is …","Returns whether the script context is Tap, aka Taproot or …","Returns whether the script context is …","","","signatures required","The public key.","The private key.","","Create a set only containing mainnet","The fingerprint of the master key associated with this …","Depending on script context, the size of a satifaction …","Maximum size, in bytes, of a satisfying witness. In …","Maximum number of witness elements used to satisfy the …","Compute the intersection of two sets","Local helper function to display error messages with …","Create a new instance of SortedMultiVec given a list of …","Origin information (fingerprint and derivation path).","Origin information (fingerprint and derivation path).","Other top level checks that are context specific","Override the computed set of valid networks","","","","","Get the len of public key when serialized based on context …","public keys inside sorted Multi","","utility function to sanity a sorted multi vec","Attempt to produce a satisfying witness for the witness …","Size, in bytes of the script-pubkey. If this Miniscript is …","The type of signature required for satisfaction","Create Terminal::Multi containing sorted pubkeys","Create a set containing testnet and regtest","","","","","","","","Returns the public version of this key.","","","","","Check top level consensus rules.","Check whether the top-level is type B","This will panic if fpk returns an uncompressed key when …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The mnemonic can be interpreted as multiple languages. Use …","Entropy was not a multiple of 32 bits or between 128-256n …","Mnemonic has a word count that is not a multiple of 6.","The English language.","A BIP39 error.","The mnemonic has an invalid checksum.","Language to be used for the mnemonic phrase.","A mnemonic code.","Type for a BIP39 mnemonic with an optional passphrase","Mnemonic contains an unknown word. Error contains the …","Type describing entropy length (aka word count) in the …","12 words mnemonic (128 bits entropy)","15 words mnemonic (160 bits entropy)","18 words mnemonic (192 bits entropy)","21 words mnemonic (224 bits entropy)","24 words mnemonic (256 bits entropy)","The list of supported languages. Language support is …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Get the index of the word in the word list.","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Create a new English Mnemonic from the given entropy. …","Create a new Mnemonic in the specified language from the …","","Generate a new Mnemonic in the given language with the …","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","Get the language of the Mnemonic.","Determine the language of the mnemonic.","Parse a mnemonic and detect the language from the enabled …","Parse a mnemonic in the given language.","Parse a mnemonic in normalized UTF8 in the given language.","Parse a mnemonic in normalized UTF8.","","","","","Convert the mnemonic back to the entropy used to generate …","Convert the mnemonic back to the entropy used to generate …","","","","Convert to seed bytes.","Convert to seed bytes with a passphrase in normalized UTF8.","","","","","","","","","","","","","","","","","","","","Get the number of words in the mnemonic.","Get an iterator over the words.","The word list for this language.","Get words from the word list that start with the given …","Trait to add functions to extract utxos and calculate fees.","The total transaction fee amount, sum of input amounts …","The transaction’s fee rate. This value will only be …","Get the TxOut for the specified input index, if it doesn’…","The address index selection strategy to use to derived an …","A derived address and the index it was found at. For …","Trait to check if a value is below the dust limit. We are …","Return the address for the current descriptor index if it …","Return a new address after incrementing the current …","Return the address for a specific descriptor index. Does …","Return the address for a specific descriptor index and …","Options to a sync.","A Bitcoin wallet","Add an external signer","Address","","","","","","","","","Bump the fee of a transaction previously created with this …","Start building a transaction.","Coin selection","Return an immutable reference to the internal database","","","","","","","","","","","Return the checksum of the public descriptor associated to …","","","","","Ensures that there are at least max_addresses addresses …","","Wallet export","Finalize a PSBT, i.e., for each input determine if …","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return a derived address using the external descriptor, …","Return the balance, separated into available, …","Returns the descriptor used to create addresses for a …","Return a fake wallet that appears to be funded for testing.","Return a derived address using the internal (change) …","get the corresponding PSBT Input for a LocalUtxo","Get the signers","Return a single transactions made and received by the …","Returns the UTXO owned by this wallet corresponding to …","HWI Signer","Child index of this address","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Check whether or not a value is below dust limit","Return whether or not a script is part of this wallet …","Type of keychain","Return an unsorted list of transactions made and received …","Return the list of unspent outputs of this wallet","Get the Bitcoin network the wallet is using.","Create a wallet.","Create a new “offline” wallet","Return the spending policies for the wallet’s descriptor","The progress tracker which may be informed when progress …","Return the “public” version of the wallet’s …","Return the secp256k1 context used for all signing …","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Sync the internal database with the blockchain","Cross-platform time","","","","","","","","","","Transaction builder","","","","","Verify transactions against the consensus rules","","","","","Deterministically generate a unique name given the …","Branch and bound coin selection","It’s possible to create spendable output from excess …","Trait for generalized coin selection algorithms","Result of a successful coin selection","Default coin selection algorithm used by TxBuilder if not …","Remaining amount after performing coin selection","Simple and dumb coin selection","It’s not possible to create spendable output from excess …","OldestFirstCoinSelection always picks the utxo with the …","","","","","","","","","","","","","","","Perform the coin selection","","","","Decide if change can be created","","","","","","","","","","","","","","","","","","","Remaining amount after deducing fees and outgoing outputs","Total fee amount for the selected utxos in satoshis","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The total value of the inputs selected from the local …","Create new instance with target size for change output","List of outputs selected for use as inputs","The total value of the inputs selected.","","","","","","","","","","","","","","","","","","","","","","","Effective amount available to create change after …","The calculated fee for the drain TxOut with the selected …","Threshold to consider amount as dust for this particular …","The deducted change output fee","Exceeding amount of current selection over outgoing value …","Structure that contains the export of a wallet","Alias for FullyNodedExport","Earliest block to rescan when looking for the wallet’s …","","","Return the internal descriptor, if present","","","Return the external descriptor","","","Export a wallet","","Returns the argument unchanged.","","","Calls U::from(self).","Arbitrary label for the wallet","","","","","","","Custom signer for Hardware Wallets","","","","","","","Returns the argument unchanged.","Create a instance from the specified device and chain","","","Calls U::from(self).","","","","","","The signer will sign all the leaves it has a key for.","Dummy identifier","The signer won’t sign the specified leaves.","The fingerprint of a BIP32 extended key","Error while signing using hardware wallets","The signer won’t sign leaves other than the ones …","Input index is out of range","PSBT Input signer","The private key in use has the right fingerprint but …","The non_witness_utxo specified is invalid","Invalid SIGHASH for the signing context in use","Legacy context","The fingerprint and derivation path are missing from the …","The private key is missing for the required public key","The non_witness_utxo field of the transaction is required …","The witness_script field of the transaction is required to …","The witness_utxo field of the transaction is required to …","The psbt contains a non-SIGHASH_ALL sighash in one of its …","The signer won’t sign any leaf.","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …","Segwit v0 context (BIP 143)","Error while computing the hash to sign","Options for a software signer","Common signer methods","Signing context","Signing error","Identifier of a signer in the SignersContainers. Used as a …","Defines the order in which signers are called","Wrapper structure to pair a signer with its context","Container for multiple signers","Taproot context (BIP 340)","Customize which taproot script-path leaves the signer …","PSBT signer","The user canceled the operation","Adds an external signer to the container for the specified …","Whether the signer should use the sighash_type set in the …","Whether we should grind ECDSA signature to ensure signing …","Create a map of public keys to secret keys","Whether the wallet should assume a specific height has …","","","","","","","","","","","","","","","","","Build a new signer container from a KeyMap","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return the secret key for the signer","","","","","","","","","","","","","","","","Finds the signer with lowest ordering for a given id in …","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Return the SignerId for this signer","","","Returns the list of identifiers of all the signers in the …","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Create a wrapped signer from a signer and a context","Default constructor","","","","Removes a signer from the container and returns it","Whether to remove partial signatures from the PSBT inputs …","Sign a single psbt input","","","Sign all the inputs of the psbt","","Whether we should try to sign a taproot transaction with …","Returns the list of signers in the container, sorted by …","Specifies which Taproot script-spend leaves we should sign …","","","","","","","","","","Whether the signer should trust the witness_utxo, if the …","Whether to try finalizing the PSBT after the inputs are …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Whether the signer can sign for the internal key or not","Return the current timestamp in seconds","BIP69 / Lexicographic","Marker type to indicate the TxBuilder is being used to …","Use both change and non-change outputs (default)","Only use non-change outputs (see …","Policy regarding the use of change outputs when creating a …","Marker type to indicate the TxBuilder is being used to …","Only use change outputs (see TxBuilder::only_spend_change)","Randomized (default)","A transaction builder","Context in which the TxBuilder is valid","Ordering of the transaction’s inputs and outputs","Unchanged","Add data as an output, using OP_RETURN","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …","Add a recipient to the internal list","Add a utxo to the internal list of unspendable utxos","Add a utxo to the internal list of utxos that must be spent","Add the list of outpoints to the internal list of UTXOs …","Set whether or not the dust limit is checked.","Explicitly tells the wallet that it is allowed to reduce …","","","","","","","","","","","Set a specific ChangeSpendPolicy. See …","","","","","","","","","","","","","Choose the coin selection algorithm","Set the current blockchain height.","","","","","","","","","","","","","","","Do not spend change outputs","Sets the address to drain excess coins to.","Spend all the available inputs. This respects filters like …","","","","","","Enable signaling RBF","Enable signaling RBF with a specific nSequence value","","","Set an absolute fee","Set a custom fee rate","Finish building the transaction.","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","Fill-in the psbt::Output::redeem_script and …","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Only spend utxos added by add_utxo.","Use a specific nLockTime while creating the transaction","Only spend change outputs","Only Fill-in the psbt::Input::witness_utxo field when …","Choose the ordering for inputs and outputs of the …","","","Set the policy path to use while creating the transaction …","Replace the recipients already added with a new list","Sign with a specific sig hash","Sort transaction inputs and outputs by TxOrdering variant","","","","","","","","","","","","","","","","","","","","","Replace the internal list of unspendable utxos with a new …","Build a transaction with a specific version","","","","","","Consensus error","Generic error","The transaction being spent doesn’t have the requested …","The transaction being spent is not available in the …","Error during validation of a tx agains the consensus rules","","","","","","","","","Returns the argument unchanged.","","","Calls U::from(self).","","","","","","Verify a transaction against the consensus rules",""],"i":[0,19,0,19,19,19,19,0,19,19,19,0,19,2,0,19,19,19,13,19,0,19,19,2,19,19,19,19,19,19,19,19,0,13,0,19,19,19,19,19,19,19,19,19,19,19,19,19,19,0,19,19,19,0,19,0,19,0,19,0,0,19,0,0,1,2,2,4,2,0,19,2,4,11,12,13,14,15,1,19,2,4,11,12,13,14,15,1,2,2,4,11,12,13,14,15,1,2,4,11,12,13,14,15,1,14,15,14,1,0,4,15,1,4,19,2,4,11,12,13,14,15,1,19,2,4,11,12,13,14,15,1,0,0,2,11,14,15,1,19,2,4,11,12,13,14,15,1,2,4,11,12,13,14,15,1,14,4,4,19,19,2,4,11,12,13,14,15,1,1,0,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,2,4,11,12,13,14,15,15,1,4,4,4,4,4,4,2,11,1,1,2,11,15,1,19,2,4,11,12,13,14,15,1,19,2,4,11,12,13,14,15,1,11,11,0,15,13,11,4,14,15,19,0,14,12,14,2,11,14,15,1,0,4,1,0,15,2,4,11,12,13,14,15,1,19,1,14,1,19,2,4,11,12,13,14,15,1,19,2,4,11,12,13,14,15,1,14,13,11,19,2,4,11,12,13,14,15,1,1,12,233,0,19,2,4,11,12,13,14,15,1,0,2,234,235,234,235,236,237,238,238,53,0,0,0,0,0,0,239,0,0,0,0,53,53,0,0,0,240,0,0,0,0,0,0,0,0,0,53,54,55,53,54,55,241,240,240,53,54,55,53,54,55,0,54,55,53,54,55,53,54,55,53,54,55,0,53,0,241,53,54,55,53,54,55,239,242,241,53,243,244,53,53,54,55,53,54,55,0,0,0,0,240,53,54,55,53,54,55,53,54,55,53,54,55,61,54,55,53,54,55,245,245,0,0,63,64,63,64,63,64,63,64,63,64,63,64,63,64,64,63,64,63,64,64,63,64,64,63,64,63,63,63,63,63,64,64,64,64,64,63,63,63,63,63,63,64,63,64,64,64,63,64,63,64,63,64,63,64,63,63,38,0,38,0,0,0,38,38,38,38,38,38,38,38,0,38,38,38,0,38,38,38,73,74,73,78,66,74,70,38,73,78,66,74,70,38,66,74,70,74,70,78,78,73,73,78,66,74,70,38,73,78,66,74,70,38,74,70,73,78,66,74,70,38,74,70,66,73,78,66,74,70,38,38,73,78,66,74,70,38,38,38,38,38,38,66,66,66,66,78,78,73,66,78,73,73,78,66,74,70,38,73,78,66,74,70,38,78,73,70,73,66,70,38,78,78,74,70,70,74,74,70,74,70,38,73,78,66,74,70,38,73,78,66,74,70,38,73,78,66,74,70,38,73,78,66,74,70,38,66,0,0,68,72,68,72,68,72,72,68,68,72,68,72,72,68,72,72,68,72,68,68,72,68,68,68,68,68,68,72,68,72,72,72,72,72,72,72,68,72,68,72,68,72,72,72,68,72,68,39,0,0,0,39,39,39,39,39,39,39,39,39,39,69,39,67,69,39,67,69,67,69,69,69,39,67,67,69,39,67,69,69,39,67,69,69,67,39,39,67,69,39,39,39,39,39,39,39,67,69,67,67,67,67,67,67,39,67,69,39,67,69,67,69,39,69,69,69,69,69,39,39,67,69,39,67,69,39,67,69,39,67,69,67,67,0,98,98,0,0,0,0,98,71,96,65,71,97,98,96,65,71,97,98,96,65,96,71,97,98,96,71,97,98,96,98,97,96,65,65,71,97,98,96,65,71,97,98,96,71,97,98,65,71,97,98,96,71,97,98,65,65,71,97,98,96,97,65,71,97,98,96,65,65,65,98,65,65,98,65,71,97,98,96,65,71,97,98,96,71,96,98,97,71,97,98,97,97,71,96,71,97,98,96,65,71,97,98,96,65,71,97,98,96,65,71,97,98,96,71,96,65,71,97,98,96,71,96,65,246,247,247,0,0,224,0,0,248,0,0,0,0,0,0,224,99,100,99,100,99,100,249,99,100,100,224,99,99,250,99,250,99,250,99,250,99,250,99,250,99,250,99,99,100,99,100,100,99,100,100,99,100,99,100,248,99,249,99,249,99,249,99,249,99,249,99,249,99,249,99,249,99,99,100,99,100,249,99,249,99,249,99,249,99,0,99,99,100,250,99,250,99,250,99,250,99,250,99,250,99,100,99,100,99,100,99,100,99,100,0,0,0,103,102,106,103,102,106,0,103,102,106,0,102,103,102,104,105,106,103,102,104,105,106,102,102,103,102,103,102,103,102,103,102,103,102,103,102,103,102,103,102,104,105,106,103,102,104,105,106,104,105,106,103,102,104,105,106,102,104,105,106,103,103,103,103,102,102,102,102,104,105,106,106,106,106,102,102,102,102,102,102,102,102,102,103,102,104,105,106,103,102,104,105,106,102,102,102,102,104,105,104,105,106,103,102,103,102,103,102,103,102,103,102,103,102,104,103,102,104,105,106,103,102,104,105,106,103,102,104,105,106,103,102,104,105,106,0,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,109,0,0,0,0,0,0,0,118,0,0,130,0,0,0,118,109,0,0,0,109,114,0,109,118,0,109,109,114,109,119,120,112,109,117,118,109,119,120,112,117,118,109,119,120,112,112,0,130,119,120,130,120,130,130,119,120,130,119,120,130,130,119,120,130,119,120,0,117,118,109,119,120,112,117,118,109,119,120,112,117,118,109,119,120,112,112,117,118,109,119,120,112,117,118,109,119,120,112,117,109,109,109,109,109,112,117,118,109,119,120,112,112,117,118,109,119,120,112,0,109,112,112,251,109,112,109,117,118,109,109,119,120,112,112,109,112,117,118,109,109,109,109,109,109,109,119,120,112,112,109,112,112,112,109,112,117,118,109,119,120,112,112,112,109,109,112,112,109,117,118,109,119,120,112,117,118,109,119,120,112,117,118,109,119,120,112,112,204,139,109,112,112,112,109,112,112,117,130,119,120,112,109,112,130,119,120,109,109,109,109,109,109,109,109,109,109,109,109,109,109,112,117,130,112,109,112,112,117,118,109,119,120,112,130,119,120,0,112,109,112,109,112,112,109,109,112,109,112,130,119,120,0,117,118,109,119,120,112,109,112,109,130,130,109,112,117,118,109,119,120,112,117,118,109,119,120,112,112,117,118,109,119,120,112,109,117,118,109,119,120,112,117,112,117,0,0,0,0,23,23,0,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,153,33,33,0,154,0,0,153,152,0,153,153,33,33,33,153,154,128,33,154,154,0,0,0,128,128,152,153,153,0,0,153,153,153,152,152,153,154,129,155,33,128,152,153,154,129,155,33,128,152,153,154,129,155,128,152,153,154,129,155,128,129,155,155,152,153,154,129,155,33,128,152,153,154,129,155,33,128,152,153,154,129,155,33,128,152,153,154,129,155,33,152,153,154,129,155,33,33,128,152,153,154,154,129,129,155,33,128,129,152,155,152,155,153,129,152,153,154,129,155,33,128,152,153,154,129,155,33,128,153,154,155,129,155,33,129,129,152,153,154,129,155,155,152,153,154,129,155,128,33,152,153,154,129,155,33,128,152,153,154,129,155,33,128,152,153,154,129,155,33,128,152,153,154,129,155,33,128,252,252,252,253,254,255,254,255,254,255,254,255,254,255,256,257,258,259,260,261,261,260,262,263,0,0,0,0,0,0,0,0,0,0,0,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,264,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,157,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,159,160,161,163,164,165,166,167,168,22,0,0,0,0,265,265,0,0,174,0,0,0,0,22,22,22,130,0,0,111,22,22,265,181,0,181,0,0,111,114,176,0,0,0,0,111,0,174,176,114,0,266,114,0,181,171,172,114,176,173,177,174,179,111,175,22,181,171,172,114,176,173,177,174,179,111,175,22,130,130,130,130,130,130,130,130,171,172,114,173,174,111,175,171,172,114,173,174,111,175,172,114,173,174,175,175,181,171,171,172,114,176,173,177,174,179,111,175,22,181,171,172,114,176,173,177,174,179,111,175,22,114,181,171,172,114,176,173,177,174,179,111,175,22,172,172,114,173,174,111,172,172,114,114,176,176,173,177,174,179,111,175,22,22,172,181,181,181,171,172,114,114,176,173,177,174,179,111,175,22,22,22,179,179,114,176,172,114,265,267,265,267,172,114,173,174,181,114,172,114,173,174,181,171,172,114,176,173,177,174,179,111,175,22,181,171,172,114,176,173,177,174,179,111,175,22,158,162,171,171,114,176,179,162,181,171,171,181,181,114,266,111,266,111,266,111,114,114,172,173,177,172,0,114,130,172,172,0,130,172,173,177,130,179,172,114,173,174,130,172,22,172,172,172,130,172,0,171,172,114,173,174,111,175,176,172,114,176,22,130,130,172,181,171,172,114,176,173,177,174,179,111,175,22,181,171,172,114,176,173,177,174,179,111,175,22,181,171,172,114,176,173,177,174,179,111,175,22,181,171,172,114,176,173,177,174,179,111,175,22,187,187,187,186,0,187,0,0,0,187,0,268,268,268,268,268,186,186,187,188,268,186,187,188,268,186,187,188,186,187,188,186,188,186,186,187,188,268,186,187,188,268,188,186,187,188,268,186,187,188,186,186,186,187,187,188,188,186,187,188,268,188,188,188,188,188,186,188,186,188,186,187,188,268,186,187,188,268,188,190,188,190,188,188,188,188,188,188,186,188,187,188,188,188,186,187,188,188,188,186,187,188,186,187,188,268,186,187,188,268,186,187,188,268,186,187,188,268,188,188,186,186,0,269,269,269,0,0,0,201,201,201,201,0,0,52,198,52,201,198,59,52,201,198,59,52,52,0,52,59,52,201,198,198,59,52,201,198,59,52,52,201,198,59,52,198,0,52,52,201,198,198,59,52,201,198,59,52,52,52,0,52,52,52,52,52,0,198,52,201,198,59,52,201,198,59,270,52,198,52,52,52,52,52,52,59,52,52,52,0,52,0,198,52,201,198,59,52,201,198,59,0,52,201,198,59,0,52,201,198,59,0,0,209,0,0,0,0,0,209,0,209,207,205,206,208,209,207,205,206,208,205,206,205,206,225,205,206,208,0,205,206,208,209,207,205,206,208,209,207,205,206,208,209,207,205,206,208,207,207,209,207,205,206,208,209,207,205,206,208,209,207,205,206,208,209,207,205,206,208,207,208,207,207,205,206,209,207,205,206,208,209,207,205,206,208,209,207,205,206,208,209,207,205,206,208,271,272,272,271,272,0,0,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,0,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,220,215,220,215,32,220,32,0,32,32,32,217,32,32,32,32,32,32,220,215,217,32,0,0,0,0,0,0,0,0,217,0,0,32,127,200,200,127,200,215,32,217,219,191,127,200,220,215,32,217,219,191,127,200,220,127,215,32,217,219,191,127,200,220,215,32,217,219,191,127,200,220,215,191,191,127,200,220,215,32,217,219,219,191,127,200,220,215,32,217,219,191,127,200,220,273,219,219,215,32,217,219,191,127,200,220,215,32,217,191,220,127,215,32,32,217,219,191,127,200,220,215,215,215,32,32,32,217,219,191,127,200,220,215,215,273,219,219,127,215,32,217,219,191,127,200,220,215,32,217,219,191,127,200,220,219,127,215,191,32,127,200,274,219,219,192,219,200,127,200,215,32,217,219,191,127,200,220,32,200,200,215,32,217,219,191,127,200,220,215,32,217,219,191,127,200,220,215,32,217,219,191,127,200,220,215,32,217,219,191,127,200,220,275,0,228,0,227,227,0,0,227,228,0,0,0,228,195,195,195,195,195,195,195,195,195,196,194,195,228,227,196,194,195,228,227,195,196,194,195,228,227,196,194,195,228,227,228,227,195,195,196,194,228,227,196,194,195,228,227,196,194,195,228,227,195,195,195,196,194,195,228,227,195,195,228,227,195,195,195,196,194,195,228,227,196,194,195,228,227,228,227,228,227,195,196,194,195,228,227,196,194,195,228,227,195,195,195,195,195,228,227,195,195,195,228,196,194,195,228,227,196,194,195,228,227,196,194,195,228,227,196,194,195,228,227,195,195,196,194,195,228,227,40,40,40,40,0,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,0,40],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[1,1],1],[2,3],[2],[4,5],[[],6],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[[10,[[9,[7,8]]]]]],[2,2],[4,4],[11,11],[12,12],[13,13],[14,14],[15,15],[1,1],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[14,14],16],[[15,15],16],0,0,0,[[],4],[[],15],[[],1],[[],4],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],0,0,[[],[[10,[2]]]],[[],[[10,[11]]]],[[],[[10,[14]]]],[[],[[10,[15]]]],[[],[[10,[1]]]],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[2,2],17],[[4,4],17],[[11,11],17],[[12,12],17],[[13,13],17],[[14,14],17],[[15,15],17],[[1,1],17],0,[[4,6],18],[[4,6],18],[[19,20],21],[[19,20],21],[[2,20],21],[[4,20],21],[[11,20],21],[[12,20],21],[[13,20],21],[[14,20],21],[[15,20],21],[[1,20],21],[[1,20],21],0,[22,19],[23,19],[24,19],[[]],[25,19],[26,19],[27,19],[28,19],[29,19],[30,19],[31,19],[32,19],[33,19],[34,19],[35,19],[36,19],[37,19],[38,19],[39,19],[40,19],[[]],[[]],[[]],[[]],[[]],[[]],[41,15],[[]],[[]],[5,4],[5,4],[5,4],[5,4],[[18,6],4],[[18,6],4],[[],18],[[],18],[1,18],[1,18],[2],[11],0,0,[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,[[[43,[42]],[43,[18]]],[[43,[15]]]],[13,44],0,[[4,4],[[43,[16]]]],[[14,14],[[43,[16]]]],[[15,15],[[43,[16]]]],[45],0,0,0,0,[2,10],[11,10],[14,10],[15,10],[1,10],0,[[4,4]],[46,1],0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],47],[[],47],0,0,[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],0,[13,48],0,[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],0,0,[[],6],[[],50],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],10],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[51,[[10,[19]]]],[[50,[43,[42]]],[[10,[19]]]],[[52,[43,[42]]],[[10,[19]]]],[53,53],[54,54],[55,55],[[]],[[]],[[]],0,[[],54],[[],55],[6],[6],[6],[6],[6],[6],[6],[6],[6],0,[[53,53],17],0,[6,[[10,[4,19]]]],[[53,20],21],[[54,20],21],[[55,20],21],[[]],[[]],[[]],[[],[[10,[19]]]],[18,[[10,[56,19]]]],[[],[[57,[53]]]],[[],18],[[],[[10,[42,19]]]],[58,[[10,[[43,[51]],19]]]],[53],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[],55],[[],54],[[]],0,[[52,[43,[42]],59],[[10,[19]]]],[[]],[[]],[[]],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[5,[43,[47]]],[[10,[19]]]],[[54,5,[43,[47]]],[[10,[19]]]],[[55,5,[43,[47]]],[[10,[19]]]],[[]],[[]],[[]],[[60,[62,[61]]],[[10,[19]]]],[[60,[62,[61]]],[[10,[19]]]],0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[63,51],[[10,[19]]]],[64,64],[[]],[6],[6],[6],[6],[[],[[10,[64]]]],[6],[6],[[64,64],17],[[63,6],[[10,[4,19]]]],[[64,20],21],[[]],[65,63],[66,63],[67,63],[68,63],[69,64],[70,64],[71,64],[72,64],[[]],[[],[[10,[63,19]]]],[[63,18],[[10,[56,19]]]],[63,[[57,[53]]]],[63,[[10,[42,19]]]],[[63,58],[[10,[[43,[51]],19]]]],[[],6],[[],6],[[]],[[]],[64,10],[[]],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[]],[[]],[[63,60,[62,[61]]],[[10,[19]]]],[[63,60,[62,[61]]],[[10,[19]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[73,51]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[66,51],[[10,[19]]]],[74,74],[70,70],[[]],[[]],[[75,[76,[73]],77],[[10,[78,38]]]],[[79,75,43,[76,[73]],77],[[10,[78,38]]]],[[],73],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[],[[10,[74]]]],[[],[[10,[70]]]],[6],[6],[6],[6],[6],[6],[[74,74],17],[[70,70],17],[[66,6],[[10,[4,19]]]],[[73,20],21],[[78,20],21],[[66,20],21],[[74,20],21],[[70,20],21],[[38,20],21],[[38,20],21],[[]],[[]],[[]],[[]],[[]],[19,38],[80,38],[[]],[81,38],[82,38],[83,38],[[],[[10,[66,19]]]],[[66,18],[[10,[56,19]]]],[66,[[57,[53]]]],[66,[[10,[42,19]]]],[78,[[76,[73]]]],[78,77],[[73,84],[[43,[51]]]],[[66,58],[[10,[[43,[51]],19]]]],[78,85],[[73,58],17],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[]],[78,17],[73,[[9,[51]]]],0,[[],73],[[[9,[78]],[87,[86]],[43,[6]]],[[10,[66,38]]]],0,[45],[[78,50,[43,[88]]],[[10,[[43,[89]],38]]]],[[78,89],[[10,[38]]]],[74,10],[70,10],0,0,0,0,[[]],[[]],[[],47],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],[[]],[[66,60,[62,[61]]],[[10,[19]]]],0,0,[[]],[[]],[[]],[[]],[[68,51],[[10,[19]]]],[72,72],[[]],[68],[6],[6],[6],[6],[[],[[10,[72]]]],[6],[6],[[72,72],17],[[68,6],[[10,[4,19]]]],[[72,20],21],[[]],[90,68],[[]],[[],[[10,[68,19]]]],[[68,18],[[10,[56,19]]]],[68,[[57,[53]]]],[68,[[10,[42,19]]]],[[68,58],[[10,[[43,[51]],19]]]],[[],6],[[],6],[[]],[[]],0,[72,10],0,0,0,[[]],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],0,0,[[]],[[]],[[68,60,[62,[61]]],[[10,[19]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[67,51],[[10,[19]]]],[69,69],[[]],0,[6],[67],[6],[6],[6],[6],[6],[[],[[10,[69]]]],[6],[6],[6],[[69,69],17],[[67,6],[[10,[4,19]]]],[[39,20],[[10,[91]]]],[[39,20],[[10,[91]]]],[[67,20],21],[[69,20],21],[[]],[34,39],[82,39],[92,39],[28,39],[93,39],[94,39],[[]],[[]],[[95,6],67],[[],[[10,[67,19]]]],[[67,18],[[10,[56,19]]]],[67,[[57,[53]]]],[67,[[10,[42,19]]]],[[67,58],[[10,[[43,[51]],19]]]],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[50,6],67],[[47,6],69],[45],0,[69,10],0,0,[[]],[[],47],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[67,60,[62,[61]]],[[10,[19]]]],[[67,3],67],0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[65,51],[[10,[19]]]],[[96,50,[43,[42]]],[[10,[19]]]],[71,71],[97,97],[98,98],[96,96],[[]],[[]],[[]],[[]],[[98,98],16],[[],97],0,[65],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[],[[10,[71]]]],[[],[[10,[97]]]],[[],[[10,[98]]]],[6],[6],[6],[6],[6],[[71,71],17],[[97,97],17],[[98,98],17],[[65,6],[[10,[4,19]]]],[[65,20],21],[[71,20],21],[[97,20],21],[[98,20],21],[[96,20],21],0,[[]],[[]],[[]],[[]],[[]],[[],[[10,[65,19]]]],[[65,18],[[10,[56,19]]]],[65,[[57,[53]]]],[[],18],[65,[[10,[42,19]]]],[[65,58],[[10,[[43,[51]],19]]]],[98],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],0,0,[[98,98],[[43,[16]]]],0,[71,10],[97,10],[98,10],0,0,0,0,[[]],[[]],[[]],[[]],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],0,0,[[]],[[]],[[]],[[]],[[]],0,0,[[65,60,[62,[61]]],[[10,[19]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[99],0,[[]],[[]],[[]],[[]],[[2,87],[[10,[19]]]],[[99,2,87],[[10,[19]]]],[100,100],[[]],[[],[[10,[19]]]],[99,[[10,[19]]]],0,[2,[[10,[[43,[42]],19]]]],[[99,2],[[10,[[43,[42]],19]]]],[101,[[10,[43,19]]]],[[99,101],[[10,[43,19]]]],[58,[[10,[[43,[51]],19]]]],[[99,58],[[10,[[43,[51]],19]]]],[[2,42],[[10,[[43,[101]],19]]]],[[99,2,42],[[10,[[43,[101]],19]]]],[[],[[10,[[43,[100]],19]]]],[99,[[10,[[43,[100]],19]]]],[[58,17],[[10,[[43,[14]],19]]]],[[99,58,17],[[10,[[43,[14]],19]]]],[44,[[10,[[43,[11]],19]]]],[[99,44],[[10,[[43,[11]],19]]]],[6],[6],[6],[6],[[],[[10,[100]]]],[6],[6],[[100,100],17],[[99,20],21],[[100,20],21],[[]],[[]],[[],[[10,[19]]]],[[],[[10,[99,19]]]],[2,[[10,[[43,[42]],19]]]],[[99,2],[[10,[[43,[42]],19]]]],[101,[[10,[43,19]]]],[[99,101],[[10,[43,19]]]],[58,[[10,[[43,[51]],19]]]],[[99,58],[[10,[[43,[51]],19]]]],[[2,42],[[10,[[43,[101]],19]]]],[[99,2,42],[[10,[[43,[101]],19]]]],[[],[[10,[[43,[100]],19]]]],[99,[[10,[[43,[100]],19]]]],[[58,17],[[10,[[43,[14]],19]]]],[[99,58,17],[[10,[[43,[14]],19]]]],[44,[[10,[[43,[11]],19]]]],[[99,44],[[10,[[43,[11]],19]]]],[2,[[10,[42,19]]]],[[99,2],[[10,[42,19]]]],[[],6],[[],6],[[]],[[]],[[],[[10,[[9,[51]],19]]]],[99,[[10,[[9,[51]],19]]]],[[[43,[2]]],[[10,[[9,[101]],19]]]],[[99,[43,[2]]],[[10,[[9,[101]],19]]]],[17,[[10,[[9,[14]],19]]]],[[99,17],[[10,[[9,[14]],19]]]],[[],[[10,[[9,[11]],19]]]],[99,[[10,[[9,[11]],19]]]],0,[[[87,[86]]],99],0,[100,10],[[2,42],[[10,[19]]]],[[99,2,42],[[10,[19]]]],[51,[[10,[19]]]],[[99,51],[[10,[19]]]],[[101,2,42],[[10,[19]]]],[[99,101,2,42],[[10,[19]]]],[100,[[10,[19]]]],[[99,100],[[10,[19]]]],[14,[[10,[19]]]],[[99,14],[[10,[19]]]],[11,[[10,[19]]]],[[99,11],[[10,[19]]]],[[]],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,[102],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[102,2,87],[[10,[19]]]],[102,[[10,[19]]]],[[103,2],[[10,[[43,[42]],19]]]],[[102,2],[[10,[[43,[42]],19]]]],[[103,101],[[10,[43,19]]]],[[102,101],[[10,[43,19]]]],[[103,58],[[10,[[43,[51]],19]]]],[[102,58],[[10,[[43,[51]],19]]]],[[103,2,42],[[10,[[43,[101]],19]]]],[[102,2,42],[[10,[[43,[101]],19]]]],[103,[[10,[[43,[100]],19]]]],[102,[[10,[[43,[100]],19]]]],[[103,58,17],[[10,[[43,[14]],19]]]],[[102,58,17],[[10,[[43,[14]],19]]]],[[103,44],[[10,[[43,[11]],19]]]],[[102,44],[[10,[[43,[11]],19]]]],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[],[[10,[104]]]],[[],[[10,[105]]]],[[],[[10,[106]]]],[6],[6],[6],[6],[6],[[102,20],21],[[104,20],21],[[105,20],21],[[106,20],21],[[],103],[[],103],[[],103],[[]],[[]],[107,102],[108,102],[99,102],[[]],[[]],[[],106],[[]],[105,106],[104,106],[[],[[10,[102,19]]]],[[102,2],[[10,[[43,[42]],19]]]],[[102,101],[[10,[43,19]]]],[[102,58],[[10,[[43,[51]],19]]]],[[102,2,42],[[10,[[43,[101]],19]]]],[102,[[10,[[43,[100]],19]]]],[[102,58,17],[[10,[[43,[14]],19]]]],[[102,44],[[10,[[43,[11]],19]]]],[[102,2],[[10,[42,19]]]],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[102,[[10,[[9,[51]],19]]]],[[102,[43,[2]]],[[10,[[9,[101]],19]]]],[[102,17],[[10,[[9,[14]],19]]]],[102,[[10,[[9,[11]],19]]]],0,0,[104,10],[105,10],[106,10],[[103,2,42],[[10,[19]]]],[[102,2,42],[[10,[19]]]],[[103,51],[[10,[19]]]],[[102,51],[[10,[19]]]],[[103,101,2,42],[[10,[19]]]],[[102,101,2,42],[[10,[19]]]],[[103,100],[[10,[19]]]],[[102,100],[[10,[19]]]],[[103,14],[[10,[19]]]],[[102,14],[[10,[19]]]],[[103,11],[[10,[19]]]],[[102,11],[[10,[19]]]],0,[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],0,[107],[[]],[[]],[[107,2,87],[[10,[19]]]],[107,[[10,[19]]]],[[],107],[[107,2],[[10,[[43,[42]],19]]]],[[107,101],[[10,[43,19]]]],[[107,58],[[10,[[43,[51]],19]]]],[[107,2,42],[[10,[[43,[101]],19]]]],[107,[[10,[[43,[100]],19]]]],[[107,58,17],[[10,[[43,[14]],19]]]],[[107,44],[[10,[[43,[11]],19]]]],[6],[6],[6],[[107,20],21],[[]],[[],[[10,[107,19]]]],[[107,2],[[10,[[43,[42]],19]]]],[[107,101],[[10,[43,19]]]],[[107,58],[[10,[[43,[51]],19]]]],[[107,2,42],[[10,[[43,[101]],19]]]],[107,[[10,[[43,[100]],19]]]],[[107,58,17],[[10,[[43,[14]],19]]]],[[107,44],[[10,[[43,[11]],19]]]],[[107,2],[[10,[42,19]]]],[[],6],[[]],[107,[[10,[[9,[51]],19]]]],[[107,[43,[2]]],[[10,[[9,[101]],19]]]],[[107,17],[[10,[[9,[14]],19]]]],[107,[[10,[[9,[11]],19]]]],[[],107],[[107,2,42],[[10,[19]]]],[[107,51],[[10,[19]]]],[[107,101,2,42],[[10,[19]]]],[[107,100],[[10,[19]]]],[[107,14],[[10,[19]]]],[[107,11],[[10,[19]]]],[[],10],[[],10],[[],49],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[109,77],[[10,[110,27]]]],[[],111],[[],111],[112,113],[[[109,[114]],42],[[109,[115]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[112,[[9,[112,8]]]],0,[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[113,[[10,[116]]]],[113,[[10,[116]]]],[113,[[10,[116]]]],[[],[[10,[116]]]],[[],[[10,[116]]]],[[],[[10,[116]]]],0,[117,117],[118,118],[109,109],[119,119],[120,120],[112,112],[[]],[[]],[[]],[[]],[[]],[[]],[[117,117],16],[[118,118],16],[[109,109],16],[[119,119],16],[[120,120],16],[[112,112],16],[112,17],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],0,[[[109,[114]],42],[[109,[115]]]],[[[109,[115]],121],[[10,[[109,[122]],123]]]],[[[109,[114]],121,42],[[10,[[109,[122]],123]]]],[109,124],[[],[[10,[109]]]],[[],[[10,[112]]]],[6],[6],[6],[6],[6],[6],[112,101],[[117,117],17],[[118,118],17],[[109,109],17],[[119,119],17],[[120,120],17],[[112,112],17],0,[109,[[10,[101,27]]]],0,[[112,125],[[10,[126]]]],[[127,128,121],[[10,[[43,[129]],23]]]],[[[109,[114]],127,128,121],[[10,[[43,[129]],23]]]],[[[112,[114,130]],127,128,121],[[10,[[43,[129]],23]]]],[[[109,[114]],121,101,[131,[42]]],[[10,[43,123]]]],[[117,20],[[10,[91]]]],[[118,20],[[10,[91]]]],[[109,20],[[10,[91]]]],[[109,20],[[10,[91]]]],[[119,20],[[10,[91]]]],[[120,20],[[10,[91]]]],[[112,20],[[10,[91]]]],[[112,20],[[10,[91]]]],[109,17],[112,17],[[]],[[]],[132,109],[133,109],[134,109],[135,109],[136,109],[137,109],[[]],[[]],[[]],[[]],[113,[[10,[112,27]]]],[50,[[10,[109,27]]]],[50,[[10,[112,27]]]],[[50,125],[[10,[112,27]]]],[50,[[10,[112,27]]]],[138,[[10,[109,27]]]],[138,[[10,[112,27]]]],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[112,6],[[43,[112]]]],[[112,6],43],[109,[[10,[27]]]],[109,[[10,[27]]]],[112,17],[112,17],[[[109,[114]]],17],[117],[118],[109],[119],[120],[112],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[]],[112,113],[[121,77],[[10,[23]]]],[[139,121,77],[[10,[23]]]],[[[109,[114]]],17],[112,17],[112,140],[112,141],[109,[[10,[142,27]]]],[112,[[10,[142,27]]]],[112,[[10,[143]]]],[[117,121],[[43,[144]]]],[112,[[43,[6]]]],[112,[[43,[6]]]],[112,[[43,[6]]]],[112,[[10,[6,27]]]],[109,[[10,[6,27]]]],[112,[[10,[6,27]]]],[[],50],[[],50],[[],50],[[[112,[145]]],[[10,[109,27]]]],[[],109],[[],109],[[[112,[119]]],[[10,[109,27]]]],[[6,[9,[8]]],[[10,[109,27]]]],[133,109],[132,109],[[],[[10,[109,27]]]],[[[112,[120]]],[[10,[109,27]]]],[[6,[9,[8]]],[[10,[109,27]]]],[[[43,[146]]],[[10,[109,27]]]],[[],[[10,[109,27]]]],[[[112,[120]]],[[10,[109,27]]]],[[6,[9,[8]]],[[10,[109,27]]]],0,0,[112,[[10,[27]]]],[101,[[10,[112,27]]]],[[121,50],[[10,[27]]]],[101,[[10,[112,27]]]],[[101,125],[[10,[112,27]]]],[[117,117],[[43,[16]]]],[[118,118],[[43,[16]]]],[[109,109],[[43,[16]]]],[[119,119],[[43,[16]]]],[[120,120],[[43,[16]]]],[[112,112],[[43,[16]]]],[[],6],[[],6],[[],6],0,[112,17],[109,[[10,[27]]]],[112,[[10,[126]]]],[[109,147],[[10,[27]]]],[112,[[10,[[9,[[9,[3,8]],8]],27]]]],[112,[[10,[[9,[[9,[3,8]],8]],27]]]],[109,[[10,[101,27]]]],[109,101],[112,6],[109,10],[112,10],[[],148],[[],148],[[],148],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],47],[[],47],[[[109,[114]],149],47],[112,[[10,[27]]]],[112,[[10,[27]]]],[109,10],[112,10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],0,[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[109,101],[[]],[[]],[[]],[[]],[[]],[[]],0,[112,17],0,[50,[[10,[47,23]]]],[50,[[10,[23]]]],[50,[[10,[47,23]]]],[50,[[10,[23]]]],0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[6],[6],[6],[[23,20],21],[[23,20],21],[150,23],[22,23],[34,23],[26,23],[[]],[151,23],[33,23],[27,23],[[],6],[[]],[45],[[],47],[[],10],[[],10],[[],49],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[152,152],[153,153],[154,154],[129,129],[155,155],[128,128],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],155],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[152,152],17],[[153,153],17],[[154,154],17],[[129,129],17],[[155,155],17],[[33,33],17],[[152,20],21],[[153,20],21],[[154,20],21],[[129,20],21],[[155,20],21],[[33,20],21],[[33,20],21],[[128,20],21],[[]],[[]],[[]],[17,154],[153,129],[[]],[[]],[[]],[[]],[[129,156],[[10,[155,33]]]],[[],18],[[],18],[152],[155],[153,47],0,[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[153,17],[154,17],[155,17],0,[[155,155],[[43,[16]]]],[45],[129,17],0,[152,10],[153,10],[154,10],[129,10],[155,10],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],47],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[77,[[10,[157,23]]]],[[[159,[[158,[119]]]],77],[[10,[157,23]]]],[[[160,[[158,[120]]]],77],[[10,[157,23]]]],[[[161,[[158,[120]]]],77],[[10,[157,23]]]],[[[163,[[162,[119]]]],77],[[10,[157,23]]]],[[[164,[[162,[119]]]],77],[[10,[157,23]]]],[[[165,[[162,[120]]]],77],[[10,[157,23]]]],[[[166,[[162,[120]]]],77],[[10,[157,23]]]],[[[167,[[162,[120]]]],77],[[10,[157,23]]]],[[[168,[[162,[120]]]],77],[[10,[157,23]]]],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[157,121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[121,77],[[10,[23]]]],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[],169],[[],111],[[114,42],115],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[112,[[10,[116]]]],[113,[[10,[116]]]],[[],[[10,[116]]]],[[[171,[170,130]]],[[171,[170,130]]]],[172,172],[114,114],[173,173],[174,174],[111,111],[175,175],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[172,172],16],[[114,114],16],[[173,173],16],[[174,174],16],0,[[],175],[6],[[[171,[130]]]],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[114,42],115],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[172,101],[[172,172],17],[[114,114],17],[[173,173],17],[[174,174],17],[[111,111],17],[[172,20],[[10,[91]]]],[[172,20],[[10,[91]]]],[[114,20],[[10,[91]]]],[[114,20],[[10,[91]]]],[[176,20],[[10,[91]]]],[[176,20],[[10,[91]]]],[[173,20],[[10,[91]]]],[[177,20],[[10,[91]]]],[[174,20],[[10,[91]]]],[[[179,[[0,[178,130]]]],20],21],[[111,20],21],[[175,20],21],[[22,20],21],[[22,20],21],[172,17],[180,[[181,[130]]]],[182,[[181,[130]]]],[[]],[[]],[[]],[[]],[115,114],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[27,22],[26,22],[[]],[[114,169],[[179,[130]]]],[[176,169],[[179,[130]]]],[50,[[10,[114]]]],[50,[[10,[176]]]],[138,[[10,[172,27]]]],[114,144],[[],[[10,[171]]]],[[],[[10,[171]]]],[[],[[10,[171]]]],[[],[[10,[171]]]],[[],18],[[],18],[[],18],[[],18],[[[181,[130]]],17],[114,17],[172],[114],[173],[174],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[[10,[179,22]]]],[[[43,[183]],144],[[10,[179,22]]]],[171,[[10,[179,22]]]],[[171,[43,[183]],144],[[10,[179,22]]]],[114,[[10,[[179,[130]],22]]]],[176,[[10,[[179,[130]],22]]]],[[[179,[130]]],[[10,[[179,[130]],22]]]],[[],[[10,[181,22]]]],[[[181,[130]]],[[10,[[181,[130]],22]]]],[171,[[10,[181,22]]]],[[[171,[130]]]],[[[181,[130]],77],[[43,[180]]]],[[[181,[130]],77,121],182],[114,17],[[],17],[111,17],[[],17],[111,17],[[],17],[111,17],[114,17],[114,17],0,0,0,[172,[[10,[142,27]]]],[[],169],[114,184],[112,[[43,[6]]]],[172,6],[172,6],[[169,169],169],[[],50],[[6,[9,[8]]],[[10,[172,27]]]],0,0,[112,[[10,[27]]]],[[[179,[130]],169],[[179,[130]]]],[[172,172],[[43,[16]]]],[[114,114],[[43,[16]]]],[[173,173],[[43,[16]]]],[[174,174],[[43,[16]]]],[[],6],0,[45],[172,[[10,[27]]]],[172,[[10,[[9,[[9,[3,8]],8]],27]]]],[172,6],[[],148],[172,113],[[],169],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[176,121],[[10,[114,185]]]],[[],47],[[],47],[[],47],[[],47],[112,[[10,[27]]]],[112,[[10,[27]]]],[172,[[10,[172]]]],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[186,186],[187,187],[188,188],[[]],[[]],[[]],[[186,186],16],[[188,188],16],[[],186],[6],[6],[6],[6],[6],[6],[6],[6],[[],[[10,[188]]]],[6],[6],[6],[6],[[186,186],17],[[187,187],17],[[188,188],17],[[186,50],[[43,[189]]]],[[186,20],[[10,[91]]]],[[186,20],[[10,[91]]]],[[187,20],[[10,[91]]]],[[187,20],[[10,[91]]]],[[188,20],[[10,[91]]]],[[188,20],[[10,[91]]]],[[]],[[]],[[]],[[]],[[],[[10,[188,187]]]],[186,[[10,[188,187]]]],[50,[[10,[188,187]]]],[[186,6],[[10,[188,187]]]],[[],[[10,[[171,[188,130]]]]]],[[],18],[[],18],[186],[188],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[188,[43,[183]],144],[[10,[[179,[130]],22]]]],[[190,[43,[183]],144],[[10,[[179,[130]],22]]]],[188,[[10,[[181,[130]],22]]]],[190,[[10,[[181,[130]],22]]]],[188,186],[[],[[10,[186,187]]]],[[],[[10,[188,187]]]],[186,[[10,[188,187]]]],[[186,50],[[10,[188,187]]]],[50,[[10,[188,187]]]],[[186,186],[[43,[16]]]],[[188,188],[[43,[16]]]],[45],[188,10],[188,[[9,[3,8]]]],[188],[[]],[[]],[[]],[188],[[188,50]],[[],47],[[],47],[[],47],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[188,6],[188,[[0,[46,170]]]],[186],[[186,50]],0,[[],[[43,[18]]]],[[],[[43,[4]]]],[6,[[43,[48]]]],0,0,0,0,0,0,0,0,0,[[52,2,191,[76,[192]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[52,58],[[10,[[195,[193,194]],19]]]],[52,[[195,[193,196]]]],0,[52,197],[[],59],[6],[6],[6],[198],[6],[6],[6],[6],[6],[[52,2],47],[6],[6],[6],[6],[[52,42],[[10,[17,19]]]],[[198,198],17],0,[[52,199,200],[[10,[17,19]]]],[[[52,[178]],20],21],[[201,20],21],[[198,20],21],[[198,20],21],[[59,20],21],[[]],[[]],[[]],[[]],[[52,201],[[10,[198,19]]]],[52,[[10,[1,19]]]],[[52,2],139],[50],[[52,201],[[10,[198,19]]]],[[52,11,[43,[202]],17],[[10,[203,19]]]],[[52,2],[[76,[127]]]],[[52,58,17],[[10,[[43,[14]],19]]]],[[52,44],[[10,[[43,[11]],19]]]],0,0,[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[101,17],[[52,101],[[10,[17,19]]]],0,[[52,17],[[10,[[9,[14]],19]]]],[52,[[10,[[9,[11]],19]]]],[52,77],[[204,[43,[204]],77],[[10,[52,19]]]],[[204,[43,[204]],77],[[10,[52,19]]]],[[52,2],[[10,[[43,[129]],19]]]],0,[[52,2],[[10,[[43,[139]],19]]]],[52,121],[[52,199,200],[[10,[17,19]]]],0,[[52,59],[[10,[19]]]],0,[[],47],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],0,[[],49],[[],49],[[],49],[[],49],0,[[]],[[]],[[]],[[]],[[43,77,121],[[10,[47,19]]]],0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[205,205],[206,206],[[]],[[]],[[[9,[12]],[9,[12]],4,18,101],[[10,[207,19]]]],[[205,[9,[12]],[9,[12]],4,18,101],[[10,[207,19]]]],[[206,[9,[12]],[9,[12]],4,18,101],[[10,[207,19]]]],[[208,[9,[12]],[9,[12]],4,18,101],[[10,[207,19]]]],[[18,4,101],209],[[],205],[[],206],[[],208],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],0,0,[[209,20],21],[[207,20],21],[[205,20],21],[[206,20],21],[[208,20],21],[[]],[[]],[[]],[[]],[[]],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[207,18],[18,208],0,[207,18],[[]],[[]],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,[[]],[[]],[210,[[43,[47]]]],[6],[6],[210,47],[[],[[10,[210]]]],[6],[[52,50,17],[[10,[210,50]]]],[[210,20],21],[[]],[50,[[10,[210]]]],[[],6],[[]],0,[210,10],[210,47],[[],10],[[],10],[[],49],[[]],0,[[]],[[]],[6],[6],[6],[[211,20],21],[[]],[[212,213],[[10,[211,214]]]],[[211,121],215],[[],6],[[]],[[211,199,200,121],[[10,[32]]]],[[],10],[[],10],[[],49],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[127,215,191,[76,[192]]],[[43,[[76,[192]]]]]],0,0,[[127,121],216],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[216,109,121],127],[215,215],[32,32],[217,217],[[[219,[[0,[170,218,178,170]]]]],[[219,[[0,[170,218,178,170]]]]]],[191,191],[127,127],[200,200],[220,220],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[215,215],16],[[191,191],16],[[],191],[[],127],[[],200],[[],220],[6],[6],[6],[6],[[[219,[[0,[218,178,170]]]]]],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[],[[43,[176]]]],[[[219,[221]]],[[43,[176]]]],[[[219,[[117,[180]]]]],[[43,[176]]]],[6],[6],[6],[6],[6],[6],[6],[6],[[215,215],17],[[32,32],17],[[217,217],17],[[191,191],17],[[220,220],17],[[127,215],[[43,[76]]]],[[215,20],21],[[32,20],21],[[32,20],21],[[217,20],21],[[[219,[[0,[178,218,178,170]]]],20],21],[[191,20],21],[[127,20],21],[[200,20],21],[[220,20],21],[184,215],[222,215],[[]],[[]],[223,32],[214,32],[[]],[[]],[[]],[[]],[[]],[[]],[[],18],[215],[121,215],[[[219,[[117,[180]]]],121],215],[[[219,[221]],121],215],[127,[[9,[215]]]],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[0,[218,178,170]],217],[[219,[[0,[218,178,170]]]]]],[[],127],[[215,215],[[43,[16]]]],[[191,191],[[43,[16]]]],[45],[[127,215,191],[[43,[[76,[192]]]]]],0,[[199,6,200,121],[[10,[32]]]],[[[219,[221]],199,6,200,121],[[10,[32]]]],[[[219,[[117,[180]]]],199,6,200,121],[[10,[32]]]],[[199,200,121],[[10,[32]]]],[[199,200,121],[[10,[32]]]],0,[127,[[9,[76]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],47],0,0,[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],18],0,0,0,0,0,0,0,0,0,0,0,0,[[[195,[224,[225,[224]],196]]],[[195,[224,[225,[224]],196]]]],[[[195,[224,[225,[224]],226]],44,203,6],[[10,[[195,[224,[225,[224]],226]],19]]]],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],196]],101,18],[[195,[224,[225,[224]],196]]]],[[[195,[224,[225,[224]],226]],44],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]],44],[[10,[[195,[224,[225,[224]],226]],19]]]],[[[195,[224,[225,[224]],226]]],[[10,[[195,[224,[225,[224]],226]],19]]]],[[[195,[224,[225,[224]],226]],17],[[195,[224,[225,[224]],226]]]],[[[195,[224,193,194]],101],[[10,[[195,[224,193,194]],19]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[195,[224,[225,[224]],226]],227],[[195,[224,[225,[224]],226]]]],[196,196],[194,194],[[[195,[170]]],[[195,[170]]]],[228,228],[227,227],[[]],[[]],[[]],[[]],[[]],[[228,228],16],[[227,227],16],[[[195,[224,[225,[224]],226]],[225,[224]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]],42],[[195,[224,[225,[224]],226]]]],[[],196],[[],194],[[],228],[[],227],[6],[6],[6],[6],[6],[6],[6],[6],[6],[6],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],196]],101],[[195,[224,[225,[224]],196]]]],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[6],[6],[6],[6],[6],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]],229],[[195,[224,[225,[224]],226]]]],[[228,228],17],[[227,227],17],[[[195,[224,[225,[224]],226]],18],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]],4],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]]],[[10,[19]]]],[[196,20],21],[[194,20],21],[[[195,[178,178,178]],20],21],[[228,20],21],[[227,20],21],[[]],[[]],[[]],[[]],[[]],[[],18],[[],18],[228],[227],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[[],6],[[],6],[[],6],[[],6],[[],6],[[]],[[]],[[]],[[]],[[]],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]],230],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]],228],[[195,[224,[225,[224]],226]]]],[[228,228],[[43,[16]]]],[[227,227],[[43,[16]]]],[[[195,[224,[225,[224]],226]],[156,[47,[9,[6]]]],2],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],196]],9],[[195,[224,[225,[224]],196]]]],[[[195,[224,[225,[224]],226]],202],[[195,[224,[225,[224]],226]]]],[[228,51]],[[]],[[]],[[]],[[]],[[]],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],49],[[],49],[[],49],[[],49],[[],49],[[[195,[224,[225,[224]],226]],[9,[44]]],[[195,[224,[225,[224]],226]]]],[[[195,[224,[225,[224]],226]],231],[[195,[224,[225,[224]],226]]]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,[[]],[[]],[6],[6],[6],[[40,20],21],[[40,20],21],[232,40],[[]],[19,40],[[],6],[[]],[45],[[],47],[[],10],[[],10],[[],49],[51,[[10,[40]]]],[[]]],"p":[[3,"Balance"],[4,"KeychainKind"],[15,"u8"],[3,"FeeRate"],[15,"f32"],[15,"usize"],[3,"u5"],[3,"Global"],[3,"Vec"],[4,"Result"],[3,"LocalUtxo"],[3,"WeightedUtxo"],[4,"Utxo"],[3,"TransactionDetails"],[3,"BlockTime"],[4,"Ordering"],[15,"bool"],[15,"u64"],[4,"Error"],[3,"Formatter"],[6,"Result"],[4,"KeyError"],[4,"Error"],[3,"Error"],[4,"Error"],[4,"Error"],[4,"Error"],[4,"Error"],[4,"PsbtParseError"],[4,"Error"],[4,"Error"],[4,"SignerError"],[4,"PolicyError"],[4,"Error"],[4,"Error"],[4,"Error"],[4,"Error"],[4,"CompactFiltersError"],[4,"EsploraError"],[4,"VerifyError"],[3,"BlockTime"],[15,"u32"],[4,"Option"],[3,"OutPoint"],[3,"Demand"],[8,"Iterator"],[3,"String"],[3,"TxOut"],[3,"TypeId"],[15,"str"],[3,"Transaction"],[3,"Wallet"],[4,"Capability"],[3,"NoopProgress"],[3,"LogProgress"],[3,"BlockHash"],[3,"HashSet"],[3,"Txid"],[3,"SyncOptions"],[3,"RefCell"],[8,"Progress"],[3,"Box"],[4,"AnyBlockchain"],[4,"AnyBlockchainConfig"],[3,"RpcBlockchain"],[3,"CompactFiltersBlockchain"],[3,"EsploraBlockchain"],[3,"ElectrumBlockchain"],[3,"EsploraBlockchainConfig"],[3,"CompactFiltersBlockchainConfig"],[3,"RpcConfig"],[3,"ElectrumBlockchainConfig"],[3,"Mempool"],[3,"BitcoinPeerConfig"],[8,"ToSocketAddrs"],[3,"Arc"],[4,"Network"],[3,"Peer"],[8,"ToTargetAddr"],[3,"SystemTimeError"],[4,"Error"],[3,"Error"],[3,"Error"],[4,"Inventory"],[3,"VersionMessage"],[3,"Path"],[8,"AsRef"],[3,"Duration"],[4,"NetworkMessage"],[3,"Client"],[3,"Error"],[3,"Transport"],[3,"ParseIntError"],[4,"Error"],[3,"BlockingClient"],[3,"RpcBlockchainFactory"],[3,"RpcSyncParams"],[4,"Auth"],[3,"SqliteDatabase"],[3,"SyncTime"],[3,"Script"],[4,"AnyDatabase"],[4,"AnyBatch"],[3,"SledDbConfiguration"],[3,"SqliteDbConfiguration"],[4,"AnyDatabaseConfig"],[3,"MemoryDatabase"],[3,"Tree"],[4,"Descriptor"],[3,"Address"],[4,"ScriptContextEnum"],[3,"Miniscript"],[4,"Terminal"],[4,"DescriptorPublicKey"],[3,"DefiniteDescriptorKey"],[4,"ScriptContextError"],[3,"DescriptorXKey"],[4,"Wildcard"],[4,"Legacy"],[4,"Segwitv0"],[3,"Secp256k1"],[3,"PublicKey"],[4,"ConversionError"],[4,"DescriptorType"],[3,"ExtParams"],[4,"AnalysisError"],[3,"SignersContainer"],[4,"BuildSatisfaction"],[3,"Policy"],[8,"ScriptContext"],[3,"Range"],[3,"Wsh"],[3,"Wpkh"],[3,"Sh"],[3,"Bare"],[3,"Pkh"],[3,"Tr"],[3,"Tree"],[6,"ExtendedDescriptor"],[3,"Iter"],[3,"PkIter"],[4,"Policy"],[4,"LiftError"],[3,"DerivationPath"],[4,"BareCtx"],[4,"TapTree"],[3,"TxIn"],[4,"SigType"],[3,"HashMap"],[4,"Error"],[4,"Error"],[4,"PkOrF"],[4,"SatisfiableItem"],[4,"Satisfaction"],[3,"Condition"],[3,"BTreeMap"],[6,"DescriptorTemplateOut"],[8,"IntoDescriptorKey"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[8,"DerivableKey"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[6,"ValidNetworks"],[8,"Clone"],[3,"GeneratedKey"],[3,"SortedMultiVec"],[3,"SinglePub"],[4,"SinglePubKey"],[3,"PrivateKeyGenerateOptions"],[4,"DescriptorSecretKey"],[3,"SinglePriv"],[8,"Debug"],[4,"DescriptorKey"],[3,"ExtendedPrivKey"],[4,"ExtendedKey"],[3,"ExtendedPubKey"],[6,"KeySource"],[3,"Fingerprint"],[3,"DescriptorKeyParseError"],[4,"Language"],[4,"Error"],[3,"Mnemonic"],[15,"u16"],[6,"MnemonicWithPassphrase"],[3,"SignerOrdering"],[8,"TransactionSigner"],[6,"DefaultCoinSelectionAlgorithm"],[3,"BumpFee"],[3,"TxBuilder"],[3,"CreateTx"],[8,"Deref"],[3,"AddressInfo"],[3,"PartiallySignedTransaction"],[3,"SignOptions"],[4,"AddressIndex"],[3,"PsbtSighashType"],[3,"Input"],[8,"IntoWalletDescriptor"],[3,"LargestFirstCoinSelection"],[3,"OldestFirstCoinSelection"],[3,"CoinSelectionResult"],[3,"BranchAndBoundCoinSelection"],[4,"Excess"],[3,"FullyNodedExport"],[3,"HWISigner"],[3,"HWIDevice"],[4,"HWIChain"],[4,"Error"],[4,"SignerId"],[6,"KeyMap"],[4,"SignerContext"],[8,"Sized"],[3,"SignerWrapper"],[4,"TapLeavesOptions"],[3,"PrivateKey"],[3,"Hash"],[4,"Error"],[8,"BatchDatabase"],[8,"CoinSelectionAlgorithm"],[8,"TxBuilderContext"],[4,"ChangeSpendPolicy"],[4,"TxOrdering"],[3,"Sequence"],[4,"LockTime"],[15,"i32"],[4,"Error"],[8,"Vbytes"],[13,"InsufficientFunds"],[13,"InvalidNetwork"],[13,"FeeRateTooLow"],[13,"FeeTooLow"],[13,"Foreign"],[8,"ConfigurableBlockchain"],[8,"BlockchainFactory"],[8,"Blockchain"],[8,"GetBlockHash"],[8,"GetHeight"],[8,"GetTx"],[8,"WalletSync"],[13,"Cookie"],[13,"UserPass"],[8,"ConfigurableDatabase"],[8,"Database"],[8,"BatchOperations"],[8,"ExtractPolicy"],[13,"PsbtTimelocks"],[13,"Complete"],[13,"Partial"],[13,"PartialComplete"],[13,"Sha256Preimage"],[13,"Hash256Preimage"],[13,"Ripemd160Preimage"],[13,"Hash160Preimage"],[13,"Thresh"],[13,"Multisig"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[8,"DescriptorTemplate"],[8,"GeneratableKey"],[8,"ExtScriptContext"],[8,"GeneratableDefaultOptions"],[4,"WordCount"],[8,"PsbtUtils"],[8,"IsDust"],[13,"Change"],[13,"NoChange"],[8,"SignerCommon"],[8,"InputSigner"],[13,"Tap"]]}\ +"bdk":{"doc":"bdk","t":[13,13,13,13,13,4,13,3,13,13,13,13,13,2,13,13,13,13,13,13,4,13,3,13,13,13,13,13,13,13,2,13,13,13,3,13,2,13,4,8,2,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,12,0,14,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,0,11,12,11,11,11,11,0,12,12,12,11,11,11,2,11,2,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,11,11,11,11,11,11,11,12,10,5,11,11,11,11,11,11,11,0,11,12,12,12,12,12,12,13,6,4,2,4,3,6,8,13,6,8,16,6,4,3,13,13,2,8,4,13,13,6,13,13,4,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,10,11,11,0,11,11,11,11,11,11,11,11,11,11,11,10,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,5,5,5,5,13,13,4,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,13,13,4,13,3,6,13,13,6,13,13,13,13,13,13,13,13,13,13,13,4,3,4,13,13,13,13,13,4,4,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,12,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3,3,3,3,3,8,6,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,8,4,4,4,16,16,8,4,13,8,8,3,8,13,13,13,16,4,6,13,13,13,16,13,3,13,8,4,13,13,13,3,3,4,3,13,6,13,13,13,5,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11,5,11,10,11,11,5,10,11,12,12,11,11,11,11,11,11,10,12,11,11,11,11,10,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,8,10,10,10,4,3,3,13,8,13,13,4,13,13,6,6,3,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,10,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,12,11,11,11,11,11,5,3,13,8,3,6,4,3,13,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,5,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,3,6,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,13,13,13,13,13,13,8,13,13,13,13,13,13,13,13,13,13,13,13,13,13,3,8,4,4,4,3,3,3,13,4,8,13,11,12,12,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,10,11,11,10,11,12,11,12,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,13,3,13,13,4,3,13,13,3,8,4,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11],"n":["Bip32","BnBNoExactMatch","BnBTotalTriesExceeded","ChecksumMismatch","Descriptor","Error","External","FeeRate","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","Foreign","Generic","HdKeyPaths","InsufficientFunds","Internal","InvalidOutpoint","InvalidPolicyPathError","IrreplaceableTransaction","Key","KeychainKind","Local","LocalUtxo","Miniscript","MiniscriptPsbt","MissingKeyOrigin","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","Psbt","SignOptions","Signer","SpendingPolicyRequired","TransactionConfirmed","TransactionDetails","TransactionNotFound","TxBuilder","UnknownUtxo","Utxo","Vbytes","Wallet","WeightedUtxo","as_byte","as_ref","as_sat_per_vb","base32_len","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain","check_base32","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","confirmation_time","confirmation_time","default","default_min_relay_fee","derivation_index","descriptor","descriptor","deserialize","deserialize","deserialize","eq","eq","eq","eq","eq","eq","fee","fee_vb","fee_wu","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fragment","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_btc_per_kvb","from_sat_per_kvb","from_sat_per_kwu","from_sat_per_vb","from_vb","from_wu","hash","hash","into","into","into","into","into","into","into","is_spent","keychain","keys","outpoint","outpoint","partial_cmp","partial_cmp","partial_cmp","provide","psbt","received","satisfaction_weight","sent","serialize","serialize","serialize","signer","sub","template","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","transaction","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","txid","txout","txout","type_id","type_id","type_id","type_id","type_id","type_id","type_id","utxo","vbytes","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet","write_base32","available","needed","required","required","outpoint","psbt_input","Bare","DerivedDescriptor","Descriptor","DescriptorError","DescriptorPublicKey","DescriptorXKey","ExtendedDescriptor","ExtractPolicy","Hardened","HdKeyPaths","IntoWalletDescriptor","Key","KeyMap","Legacy","Miniscript","None","Pkh","Policy","ScriptContext","Segwitv0","Sh","Single","TapKeyOrigins","Tr","Unhardened","Wildcard","Wpkh","Wsh","XPub","address","as_enum","as_enum","as_inner","at_derivation_index","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","calc_checksum","check_global_consensus_validity","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","cmp","contains_raw_pkh","derivation_path","derive","derived_descriptor","derived_descriptor","desc_type","deserialize","deserialize","dust_value","encode","eq","eq","eq","eq","eq","eq","error","explicit_script","ext","ext_check","extract_policy","extract_policy","extract_policy","find_derivation_index_for_spk","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","for_each_key","from","from","from","from","from","from","from","from","from","from","from","from","from_ast","from_str","from_str","from_str_ext","from_str_insane","from_tree","from_tree","get_nth_child","get_nth_pk","get_satisfaction","get_satisfaction_mall","has_mixed_timelocks","has_repeated_keys","has_wildcard","hash","hash","hash","hash","hash","hash","into","into","into","into","into","into","into_inner","into_wallet_descriptor","into_wallet_descriptor","is_deriveable","is_non_malleable","iter","iter_pk","lift","lift","lift_check","matches","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","name_str","name_str","name_str","new_bare","new_pk","new_pkh","new_sh","new_sh_sortedmulti","new_sh_with_wpkh","new_sh_with_wsh","new_sh_wpkh","new_sh_wsh","new_sh_wsh_sortedmulti","new_tr","new_wpkh","new_wsh","new_wsh_sortedmulti","node","origin","other_top_level_checks","parse","parse_descriptor","parse_insane","parse_with_ext","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pk_len","pk_len","policy","requires_sig","sanity_check","sanity_check","satisfy","satisfy","satisfy_malleable","script_code","script_pubkey","script_size","serialize","serialize","sig_type","sig_type","sig_type","template","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string_with_secret","top_level_checks","top_level_type_check","translate_pk","translate_pk","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","vzip","vzip","wildcard","within_resource_limits","xkey","calc_checksum","calc_checksum_bytes","get_checksum","get_checksum_bytes","Base58","Bip32","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","Pk","Policy","borrow","borrow_mut","fmt","fmt","from","from","from","from","from","from","from","from","into","provide","to_string","try_from","try_into","type_id","vzip","AbsoluteTimelock","AddOnLeaf","AddOnPartialComplete","BuildSatisfaction","Complete","Condition","ConditionMap","EcdsaSignature","Fingerprint","FoldedConditionMap","Hash160Preimage","Hash256Preimage","IncompatibleConditions","IndexOutOfRange","MixedTimelockUnits","Multisig","None","None","NotEnoughItemsSelected","Partial","PartialComplete","PkOrF","Policy","PolicyError","Psbt","PsbtTimelocks","Pubkey","RelativeTimelock","Ripemd160Preimage","Satisfaction","SatisfiableItem","SchnorrSignature","Sha256Preimage","Thresh","XOnlyPubkey","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","contribution","csv","default","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","get_condition","hash","hash","id","id","into","into","into","into","into","into","into","is_leaf","is_leaf","is_null","item","partial_cmp","provide","requires_path","satisfaction","serialize","serialize","serialize","serialize","serialize","timelock","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","current_height","input_max_height","psbt","condition","conditions","conditions","items","items","m","m","n","n","sorted","sorted","hash","hash","hash","hash","items","keys","threshold","threshold","value","value","Bip44","Bip44Public","Bip49","Bip49Public","Bip84","Bip84Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2Wpkh","P2Wpkh_P2Sh","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","build","build","build","build","build","build","build","build","build","from","from","from","from","from","from","from","from","from","into","into","into","into","into","into","into","into","into","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","Entropy","Error","ExtScriptContext","ExtendedKey","FullKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","Key","KeyError","KeyMap","Legacy","Message","Miniscript","Options","Private","PrivateKeyGenerateOptions","Public","ScriptContext","ScriptContextEnum","Segwitv0","Single","Single","SinglePriv","SinglePub","SinglePubKey","SortedMultiVec","Tap","ValidNetworks","XOnly","XPrv","XPub","any_network","as_enum","at_derivation_index","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_global_consensus_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_policy_validity","check_local_validity","check_terminal_non_malleable","check_witness","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","compressed","default","deref","derive","encode","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_public","from_secret","from_str","from_str","from_tree","full_derivation_path","generate","generate_default","generate_with_entropy","generate_with_entropy_default","has_secret","has_wildcard","hash","hash","hash","hash","into","into","into","into","into","into","into","into","into","into","into","into","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_extended_key","into_key","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_segwit_v0","is_segwit_v0","is_taproot","is_taproot","is_uncompressed","is_x_only_key","k","key","key","lift","mainnet_network","master_fingerprint","max_satisfaction_size","max_satisfaction_size","max_satisfaction_witness_elements","merge_networks","name_str","new","origin","origin","other_top_level_checks","override_valid_networks","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pks","provide","sanity_check","satisfy","script_size","sig_type","sorted_node","test_networks","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_public","to_string","to_string","to_string","to_string","top_level_checks","top_level_type_check","translate_pk","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","PsbtUtils","fee_amount","fee_rate","get_utxo_for","AddressIndex","AddressInfo","Balance","Descriptor","IsDust","LastUnused","New","NewError","Peek","Persist","Update","UpdateError","Wallet","add","add_signer","address","apply_update","as_chain_graph","as_graph","as_ref","as_ref","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build_fee_bump","build_tx","cancel_tx","checkpoints","clone","clone_into","coin_selection","commit","confirmed","default","deref","derivation_index","derivation_of_spk","descriptor_checksum","deserialize","eq","eq","export","finalize_psbt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","get_address","get_balance","get_descriptor_for_keychain","get_internal_address","get_psbt_input","get_signers","get_tx","get_utxo","immature","index","insert_checkpoint","insert_tx","into","into","into","into","into","is_dust","is_mine","keychain","keychanins","latest_checkpoint","list_transactions","list_unspent","network","new","new_no_persist","next_derivation_index","policies","provide","public_descriptor","secp_ctx","serialize","sign","signer","spks_of_all_keychains","spks_of_keychain","staged","to_owned","to_string","to_string","to_string","total","transactions","trusted_pending","trusted_spendable","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","tx_builder","type_id","type_id","type_id","type_id","type_id","untrusted_pending","vzip","vzip","vzip","vzip","vzip","wallet_name_from_descriptor","BranchAndBoundCoinSelection","Change","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","Excess","LargestFirstCoinSelection","NoChange","OldestFirstCoinSelection","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone_into","clone_into","clone_into","coin_select","coin_select","coin_select","coin_select","decide_change","default","default","default","excess","fee_amount","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","into","into","into","into","into","local_selected_amount","new","selected","selected_amount","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","amount","change_fee","dust_threshold","fee","remaining_amount","FullyNodedExport","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","descriptor","deserialize","export_wallet","fmt","from","from_str","into","label","serialize","to_string","try_from","try_into","type_id","vzip","All","Dummy","Exclude","Fingerprint","Include","InputIndexOutOfRange","InputSigner","InvalidKey","InvalidNonWitnessUtxo","InvalidSighash","Legacy","MissingHdKeypath","MissingKey","MissingNonWitnessUtxo","MissingWitnessScript","MissingWitnessUtxo","NonStandardSighash","None","PkHash","Segwitv0","SighashError","SignOptions","SignerCommon","SignerContext","SignerError","SignerId","SignerOrdering","SignerWrapper","SignersContainer","Tap","TapLeavesOptions","TransactionSigner","UserCanceled","add_external","allow_all_sighashes","allow_grinding","as_key_map","assume_height","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","default","default","deref","descriptor_secret_key","descriptor_secret_key","descriptor_secret_key","eq","eq","eq","eq","eq","find","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","hash","id","id","id","ids","into","into","into","into","into","into","into","into","new","new","partial_cmp","partial_cmp","provide","remove","remove_partial_sigs","sign_input","sign_input","sign_input","sign_transaction","sign_transaction","sign_with_tap_internal_key","signers","tap_leaves_options","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","trust_witness_utxo","try_finalize","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","is_internal_key","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","Untouched","add_data","add_foreign_utxo","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_dust","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_policy","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","coin_selection","current_height","default","default","default","default","do_not_spend_change","drain_to","drain_wallet","enable_rbf","enable_rbf_with_sequence","eq","eq","fee_absolute","fee_rate","finish","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","hash","hash","include_output_redeem_witness_script","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","set_recipients","sighash","sort_tx","to_owned","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","unspendable","version","vzip","vzip","vzip","vzip","vzip"],"q":["bdk","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Error","","","","bdk::Utxo","","bdk::descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::checksum","","","","bdk::descriptor::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy::BuildSatisfaction","","","bdk::descriptor::policy::Satisfaction","","","","","","","","","","","bdk::descriptor::policy::SatisfiableItem","","","","","","","","","","bdk::descriptor::template","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::psbt","","","","bdk::wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::coin_selection::Excess","","","","","bdk::wallet::export","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer::SignerContext","bdk::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["BIP32 error","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","Descriptor checksum mismatch","Error related to the parsing and usage of descriptors","Errors that can be thrown by the Wallet","External","Fee rate","When bumping a tx the fee rate requested is lower than …","Node doesn’t have data to estimate a fee rate","When bumping a tx the absolute fee requested is lower than …","A UTXO owned by another wallet.","Generic error","","Wallet’s UTXO set is not enough to cover recipient’s …","Internal, usually used for change outputs","Requested outpoint doesn’t exist in the tx (vout greater …","Error while extracting and manipulating policies","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Error while working with keys","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","Miniscript error","Miniscript PSBT error","In order to use the TxBuilder::add_global_xpubs option …","Cannot build a tx without recipients","manually_selected_only option is selected but no utxo has …","Output created is under the dust limit, 546 satoshis","Partially signed bitcoin transaction error","","Signing error","Spending policy is not compatible with this KeychainKind","Happens when trying to bump a transaction that is already …","A wallet transaction","Thrown when a tx is not found in the internal database","","Happens when trying to spend an UTXO that is not in the …","An unspent transaction output (UTXO).","Trait implemented by types that can be used to measure …","","A Utxo with its satisfaction_weight.","Return KeychainKind as a byte","","Return the value as satoshi/vbyte","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The confirmation time for transaction containing this utxo","If the transaction is confirmed, contains height and Unix …","","Create a new FeeRate with the default min relay fee value","The derivation index for the script pubkey in the wallet","Descriptors","Macro to write full descriptors with code","","","","","","","","","","Fee value in sats if it was available.","Calculate absolute fee in Satoshis using size in virtual …","Calculate absolute fee in Satoshis using size in weight …","","","","","","","","","Macro to write descriptor fragments with code","","","Returns the argument unchanged.","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Calculate fee rate from fee and vbytes.","Calculate fee rate from fee and weight units (wu).","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Whether this UTXO is spent or not","Type of keychain","Key formats","Get the location of the UTXO","Reference to a transaction output","","","","","Additional functions on the rust-bitcoin …","Received value (sats) Sum of owned outputs of this …","The weight of the witness data and scriptSig expressed in …","Sent value (sats) Sum of owned inputs of this transaction.","","","","","","","","","","","","","","Optional transaction","","","","","","","","","","","","","","","Transaction id","Get the TxOut of the UTXO","Transaction output","","","","","","","","The UTXO","Convert weight units to virtual bytes.","Get the version of BDK at runtime","","","","","","","","Wallet","","Sats available for spending","Sats needed for some transaction","Required fee rate (satoshi/vbyte)","Required fee absolute value (satoshi)","The location of the output.","The information about the input we require to add it to a …","A raw scriptpubkey (including pay-to-pubkey) under Legacy …","Alias for a Descriptor that contains extended derived keys","Script descriptor","","The descriptor pubkey, either a single pubkey or an xpub.","An extended key with origin, derivation path, and wildcard.","Alias for a Descriptor that can contain extended keys …","Trait implemented on Descriptors to add a method to …","Unhardened wildcard, e.g. *h","Alias for the type of maps that represent derivation paths …","Trait for types which can be converted into an …","The consensus key associated with the type. Must be a …","Alias type for a map of public key to secret key","Legacy ScriptContext To be used as P2SH scripts For …","Top-level script AST type","No wildcard","Pay-to-PubKey-Hash","","The ScriptContext for Miniscript. Additional type …","Segwitv0 ScriptContext","Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)","Single public key.","Alias for the type of maps that represent taproot key …","Pay-to-Taproot","Unhardened wildcard, e.g. *","Whether a descriptor has a wildcard in it","Pay-to-Witness-PubKey-Hash","Pay-to-Witness-ScriptHash with Segwitv0 context","Extended public key (xpub).","Computes the Bitcoin address of the descriptor, if one …","","","Get a reference to the inner AstElem representing the root …","Replaces all wildcards (i.e. /*) in the descriptor with a …","","","","","","","","","","","","","Enumerates all child nodes of the current AST node (self) …","","Depending on script Context, some of the Terminals might …","","","Depending on script Context, some of the script resource …","","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","","","Policy rules at the Miniscript satisfaction time. It is …","","","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","","","Check whether the given satisfaction is valid under the …","","","Descriptor checksum","","","","","","","","","","","","","","","","","","","Whether the given miniscript contains a raw pkh fragment","The derivation path","Deprecated name for [at_derivation_index].","Convert all the public keys in the descriptor to …","Convert all the public keys in the descriptor to …","Get the DescriptorType of Descriptor","","","","Encode as a Bitcoin script","","","","","","","Descriptor errors","Computes the the underlying script before any hashing is …","Additional information helpful for extra analysis.","Check whether the miniscript follows the given Extra …","Extract the spending policy","","","Utility method for deriving the descriptor at each index …","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Add type information(Type and Extdata) to Miniscript based …","","Parse a Miniscript from string and perform sanity checks …","Attempt to parse an Miniscripts that don’t follow the …","Attempt to parse an insane(scripts don’t clear sanity …","Parse an expression tree into a descriptor.","Parse an expression tree into a Miniscript. As a general …","Returns child node with given index, if any","Returns Option::Some with cloned n’th public key from …","Returns satisfying non-malleable witness and scriptSig to …","Returns a possilbly mallable satisfying non-malleable …","Whether the miniscript contains a combination of timelocks","Whether the miniscript has repeated Pk or Pkh","Whether or not the descriptor has any wildcards i.e. /*.","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Extracts the AstElem representing the root of the …","Convert to wallet descriptor","","Whether or not the descriptor has any wildcards","Whether the miniscript is malleable","Creates a new Iter iterator that will iterate over all …","Creates a new PkIter iterator that will iterate over all …","","","Lifting corresponds conversion of miniscript into Policy […","Compares this key with a keysource and returns the …","Depending on script context, the size of a satifaction …","","","Maximum size, in bytes, of a satisfying witness. For …","Computes an upper bound on the weight of a satisfying …","Maximum number of witness elements used to satisfy the …","Local helper function to display error messages with …","","","Create a new bare descriptor from witness script Errors …","Create a new pk descriptor","Create a new PkH descriptor","Create a new sh for a given redeem script Errors when …","Create a new sh sortedmulti descriptor with threshold k …","Create a new sh wrapper for the given wpkh descriptor","Create a new sh wrapper for the given wsh descriptor","Create a new sh wrapped wpkh from Pk. Errors when …","Create a new sh wrapped wsh descriptor with witness script …","Create a new sh wrapped wsh sortedmulti descriptor from …","Create new tr descriptor Errors when miniscript exceeds …","Create a new Wpkh descriptor Will return Err if …","Create a new wsh descriptor from witness script Errors …","Create a new wsh sorted multi descriptor Errors when …","A node in the Abstract Syntax Tree(","Origin information","Other top level checks that are context specific","Attempt to parse a Script into Miniscript representation.","Parse a descriptor that may contain secret keys","Attempt to parse an insane(scripts don’t clear sanity …","Attempt to parse an miniscript with extra features that …","","","","","","","Get the len of public key when serialized based on context …","","","Descriptor policy","Whether all spend paths of miniscript require a signature","Checks whether the descriptor is safe.","Check whether the underlying Miniscript is safe under the …","Attempts to produce a non-malleable satisfying witness and …","Attempt to produce non-malleable satisfying witness for the","Attempt to produce a malleable satisfying witness for the …","Computes the scriptCode of a transaction output.","Computes the scriptpubkey of the descriptor.","Size, in bytes of the script-pubkey. If this Miniscript is …","","","The type of signature required for satisfaction","","","Descriptor templates","","","","","","","","","Serialize a descriptor to string with its secret keys","Check top level consensus rules.","Check whether the top-level is type B","Converts a descriptor using abstract keys to one using …","Translates a struct from one generic to another where the …","","","","","","","","","","","","","The correctness and malleability type information for the …","","","","","","","Computes the scriptSig that will be in place for an …","","","","","","","Whether the descriptor is wildcard","Whether the miniscript can exceed the resource …","The extended key","Compute the checksum of a descriptor, excludes any …","Compute the checksum bytes of a descriptor, excludes any …","Compute the checksum of a descriptor","Compute the checksum bytes of a descriptor","Error during base58 decoding","BIP32 error","Errors related to the parsing and usage of descriptors","The descriptor contains hardened derivation steps on …","Hex decoding error","Invalid byte found in the descriptor checksum","The provided descriptor doesn’t match its checksum","Invalid HD Key path, such as having a wildcard but a …","Error thrown while working with keys","Miniscript error","Key-related error","Error while extracting and manipulating policies","","","","","Returns the argument unchanged.","","","","","","","","Calls U::from(self).","","","","","","","Absolute timeclock timestamp","Can not add to an item that is Satisfaction::None or …","Can not add to an item that is …","Options to build the satisfaction field in the policy","Can satisfy the policy item","An extra condition that must be satisfied but that is out …","Type for a map of sets of Condition items keyed by each set…","ECDSA Signature for a raw public key","An extended key fingerprint","Type for a map of folded sets of Condition items keyed by …","SHA256 then RIPEMD160 preimage hash","Double SHA256 preimage hash","Incompatible conditions (not currently used)","Index out of range for an item to satisfy a …","Can not merge CSV or timelock values unless both are less …","Multi-signature public keys with threshold count","Cannot satisfy or contribute to the policy item","Don’t generate satisfaction field","Not enough items are selected to satisfy a …","Only a partial satisfaction of some kind of threshold …","Can reach the threshold of some kind of threshold policy","A unique identifier for a key","Descriptor spending policy","Errors that can happen while extracting and manipulating …","Analyze the given PSBT to check for existing signatures","Like Psbt variant and also check for expired timelocks","A legacy public key","Relative timelock locktime","RIPEMD160 preimage hash","Represent if and how much a policy item is satisfied by …","An item that needs to be satisfied","Schnorr Signature for a raw public key","SHA256 preimage hash","Threshold items with threshold count","A x-only public key","","","","","","","","","","","","","","","","","","","","","","","","","","","How the wallet’s descriptor can satisfy this policy node","Optional CheckSequenceVerify condition","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return the conditions that are set by the spending policy …","","","Returns a unique id for the SatisfiableItem","Identifier for this policy node","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns whether the SatisfiableItem is a leaf item","Returns whether the Satisfaction is a leaf item","Returns true if there are no extra conditions to verify","Type of this policy node","","","Return whether or not a specific path in the policy tree …","How much a given PSBT already satisfies this policy node …","","","","","","Optional timelock condition","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Current blockchain height","The highest confirmation height between the inputs CSV …","Given PSBT","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","The items that can be satisfied by the descriptor or are …","The items that can be satisfied by the descriptor","Threshold","Threshold","Total number of items","Total number of items","Whether the items are sorted in lexicographic order (used …","Whether the items are sorted in lexicographic order (used …","The digest value","The digest value","The digest value","The digest value","The policy items","The raw public key or extended key fingerprint","The required threshold count","The required threshold count","The timelock value","The timelock value","BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/*)","BIP44 public template. Expands to pkh(key/{0,1}/*)","BIP49 template. Expands to …","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))","BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/*)","BIP84 public template. Expands to wpkh(key/{0,1}/*)","Trait for descriptor templates that can be built into a …","Type alias for the return type of DescriptorTemplate, …","P2PKH template. Expands to a descriptor pkh(key)","P2WPKH template. Expands to a descriptor wpkh(key)","P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))","","","","","","","","","","","","","","","","","","","Build the complete descriptor","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","BIP32 error","Trait for keys that can be derived.","Container for public or secret keys","The descriptor pubkey, either a single pubkey or an xpub.","The descriptor secret key, either a single private key or …","Type specifying the amount of entropy required e.g. [u8;32]","Returned error in case of failure","Trait that adds extra useful methods to ScriptContexts","Enum for extended keys that can be either xprv or xpub","A bitcoin public key (compressed or uncompressed).","Trait that allows generating a key with the default options","Trait for keys that can be generated","Output of a GeneratableKey key generation","Trait for objects that can be turned into a public or …","The key has an invalid checksum","The key is not valid for the given network","The key cannot exist in the given script context","The consensus key associated with the type. Must be a …","Errors thrown while working with keys","Alias type for a map of public key to secret key","Legacy scripts","Custom error message","Miniscript error","Extra options required by the generate_with_entropy","A private extended key, aka an xprv","Options for generating a PrivateKey","A public extended key, aka an xpub","The ScriptContext for Miniscript. Additional type …","Enum representation of the known valid ScriptContexts","Segwitv0 scripts","Single public key.","Single private key.","A descriptor bitcoin::PrivateKey with optional origin …","A descriptor SinglePubKey with optional origin information.","Single public key without any origin or range information.","Contents of a “sortedmulti” descriptor","Taproot scripts","Set of valid networks for a key","An xonly public key.","Extended private key (xpriv).","Extended public key (xpub).","Create a set containing mainnet, testnet, signet, and …","Returns the ScriptContext as a ScriptContextEnum","Replaces any wildcard (i.e. /*) in the key with a …","","","","","","","","","","","","","","","","","","","","","","","","","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the script resource …","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","Policy rules at the Miniscript satisfaction time. It is …","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","Check whether the given satisfaction is valid under the …","","","","","","","","","","","","","","","","","","","Whether the generated key should be “compressed” or not","","","Deprecated name of [at_derivation_index].","Encode as a Bitcoin script","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Create an instance given a public key and a set of valid …","Create an instance given a secret key and a set of valid …","","","Parse an expression tree into a SortedMultiVec","Full path, from the master key","Generate a key given the options with a random entropy","Generate a key with the default options and a random …","Generate a key given the extra options and the entropy","Generate a key with the default options and a given entropy","Return whether or not the key contains the private data","Whether or not the key has a wildcard","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Turn the key into a DescriptorKey within the requested …","Consume self and turn it into a DescriptorKey by adding …","","","","","","Consume self and turn it into an ExtendedKey","","","Consumes self and returns the key","Transform the ExtendedKey into an ExtendedPrivKey for the …","Transform the ExtendedKey into an ExtendedPubKey for the …","Whether or not the key has a wildcard","Returns whether the script context is Legacy","Returns whether the script context is …","Returns whether the script context is Segwitv0","Returns whether the script context is …","Returns whether the script context is Tap, aka Taproot or …","Returns whether the script context is …","","","signatures required","The public key.","The private key.","","Create a set only containing mainnet","The fingerprint of the master key associated with this …","Depending on script context, the size of a satifaction …","Maximum size, in bytes, of a satisfying witness. In …","Maximum number of witness elements used to satisfy the …","Compute the intersection of two sets","Local helper function to display error messages with …","Create a new instance of SortedMultiVec given a list of …","Origin information (fingerprint and derivation path).","Origin information (fingerprint and derivation path).","Other top level checks that are context specific","Override the computed set of valid networks","","","","","Get the len of public key when serialized based on context …","public keys inside sorted Multi","","utility function to sanity a sorted multi vec","Attempt to produce a satisfying witness for the witness …","Size, in bytes of the script-pubkey. If this Miniscript is …","The type of signature required for satisfaction","Create Terminal::Multi containing sorted pubkeys","Create a set containing testnet and regtest","","","","","","","","Returns the public version of this key.","","","","","Check top level consensus rules.","Check whether the top-level is type B","This will panic if fpk returns an uncompressed key when …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Trait to add functions to extract utxos and calculate fees.","The total transaction fee amount, sum of input amounts …","The transaction’s fee rate. This value will only be …","Get the TxOut for the specified input index, if it doesn’…","The address index selection strategy to use to derived an …","A derived address and the index it was found at. For …","Balance differentiated in various categories.","There was problem with the descriptors passed in","Trait to check if a value is below the dust limit. We are …","Return the address for the current descriptor index if it …","Return a new address after incrementing the current …","Error returned from Wallet::new","Return the address for a specific descriptor index. Does …","We were unable to load the wallet’s data from the …","The update to a Wallet used in Wallet::apply_update. This …","Error indicating that something was wrong with an Update<T>…","A Bitcoin wallet","","Add an external signer","Address","Applies an update to the wallet and stages the changes …","Get a reference to the inner ChainGraph.","Get a reference to the inner TxGraph.","","","","","","","","","","","","","Bump the fee of a transaction previously created with this …","Start building a transaction.","Informs the wallet that you no longer intend to broadcast …","Get all the checkpoints the wallet is currently storing …","","","Coin selection","Commits all curently staged changed to the persistence …","Confirmed and immediately spendable balance","","","The derivation index of this wallet. It will return None …","Finds how the wallet derived the script pubkey spk.","Return the checksum of the public descriptor associated to …","","","","Wallet export","Finalize a PSBT, i.e., for each input determine if …","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return a derived address using the external descriptor, …","Return the balance, separated into available, …","Returns the descriptor used to create addresses for a …","Return a derived address using the internal (change) …","get the corresponding PSBT Input for a LocalUtxo","Get the signers","Return a single transactions made and received by the …","Returns the utxo owned by this wallet corresponding to …","All coinbase outputs not yet matured","Child index of this address","Add a new checkpoint to the wallet’s internal view of …","Add a transaction to the wallet’s internal view of the …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Check whether or not a value is below dust limit","Return whether or not a script is part of this wallet …","Type of keychain","Iterator over all keychains in this wallet","Returns the latest checkpoint.","Deprecated. use Wallet::transactions instead.","Return the list of unspent outputs of this wallet","Get the Bitcoin network the wallet is using.","Create a wallet from a descriptor (and an optional …","Creates a wallet that does not persist data.","The index of the next address that you would get if you …","Return the spending policies for the wallet’s descriptor","","Return the “public” version of the wallet’s …","Return the secp256k1 context used for all signing …","","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Returns a iterators of all the script pubkeys for the …","Gets an iterator over all the script pubkeys in a single …","Returns the changes that will be staged with the next call …","","","","","Get the whole balance visible to the wallet.","Iterate over the transactions in the wallet in order of …","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","","","","","Transaction builder","","","","","","Unconfirmed UTXOs received from an external wallet","","","","","","Deterministically generate a unique name given the …","Branch and bound coin selection","It’s possible to create spendable output from excess …","Trait for generalized coin selection algorithms","Result of a successful coin selection","Default coin selection algorithm used by TxBuilder if not …","Remaining amount after performing coin selection","Simple and dumb coin selection","It’s not possible to create spendable output from excess …","OldestFirstCoinSelection always picks the utxo with the …","","","","","","","","","","","","","","","","","Perform the coin selection","","","","Decide if change can be created","","","","Remaining amount after deducing fees and outgoing outputs","Total fee amount for the selected utxos in satoshis","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The total value of the inputs selected from the local …","Create new instance with target size for change output","List of outputs selected for use as inputs","The total value of the inputs selected.","","","","","","","","","","","","","","","","","","","","","","","","Effective amount available to create change after …","The calculated fee for the drain TxOut with the selected …","Threshold to consider amount as dust for this particular …","The deducted change output fee","Exceeding amount of current selection over outgoing value …","Structure that contains the export of a wallet","Alias for FullyNodedExport","Earliest block to rescan when looking for the wallet’s …","","","Return the internal descriptor, if present","Return the external descriptor","","Export a wallet","","Returns the argument unchanged.","","Calls U::from(self).","Arbitrary label for the wallet","","","","","","","The signer will sign all the leaves it has a key for.","Dummy identifier","The signer won’t sign the specified leaves.","The fingerprint of a BIP32 extended key","The signer won’t sign leaves other than the ones …","Input index is out of range","PSBT Input signer","The private key in use has the right fingerprint but …","The non_witness_utxo specified is invalid","Invalid SIGHASH for the signing context in use","Legacy context","The fingerprint and derivation path are missing from the …","The private key is missing for the required public key","The non_witness_utxo field of the transaction is required …","The witness_script field of the transaction is required to …","The witness_utxo field of the transaction is required to …","The psbt contains a non-SIGHASH_ALL sighash in one of its …","The signer won’t sign any leaf.","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …","Segwit v0 context (BIP 143)","Error while computing the hash to sign","Options for a software signer","Common signer methods","Signing context","Signing error","Identifier of a signer in the SignersContainers. Used as a …","Defines the order in which signers are called","Wrapper structure to pair a signer with its context","Container for multiple signers","Taproot context (BIP 340)","Customize which taproot script-path leaves the signer …","PSBT signer","The user canceled the operation","Adds an external signer to the container for the specified …","Whether the signer should use the sighash_type set in the …","Whether we should grind ECDSA signature to ensure signing …","Create a map of public keys to secret keys","Whether the wallet should assume a specific height has …","","","","","","","","","","","","","","","","","Build a new signer container from a KeyMap","","","","","","","","","","","","","","","","","","","","","","","","Return the secret key for the signer","","","","","","","","Finds the signer with lowest ordering for a given id in …","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Return the SignerId for this signer","","","Returns the list of identifiers of all the signers in the …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Create a wrapped signer from a signer and a context","Default constructor","","","","Removes a signer from the container and returns it","Whether to remove partial signatures from the PSBT inputs …","Sign a single psbt input","","","Sign all the inputs of the psbt","","Whether we should try to sign a taproot transaction with …","Returns the list of signers in the container, sorted by …","Specifies which Taproot script-spend leaves we should sign …","","","","","","","","","","Whether the signer should trust the witness_utxo, if the …","Whether to try finalizing the PSBT after the inputs are …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Whether the signer can sign for the internal key or not","BIP69 / Lexicographic","Marker type to indicate the TxBuilder is being used to …","Use both change and non-change outputs (default)","Only use non-change outputs (see …","Policy regarding the use of change outputs when creating a …","Marker type to indicate the TxBuilder is being used to …","Only use change outputs (see TxBuilder::only_spend_change)","Randomized (default)","A transaction builder","Context in which the TxBuilder is valid","Ordering of the transaction’s inputs and outputs","Unchanged","Add data as an output, using OP_RETURN","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …","Add a recipient to the internal list","Add a utxo to the internal list of unspendable utxos","Add a utxo to the internal list of utxos that must be spent","Add the list of outpoints to the internal list of UTXOs …","Set whether or not the dust limit is checked.","Explicitly tells the wallet that it is allowed to reduce …","","","","","","","","","","","Set a specific ChangeSpendPolicy. See …","","","","","","","","","","","","","Choose the coin selection algorithm","Set the current blockchain height.","","","","","Do not spend change outputs","Sets the address to drain excess coins to.","Spend all the available inputs. This respects filters like …","Enable signaling RBF","Enable signaling RBF with a specific nSequence value","","","Set an absolute fee","Set a custom fee rate","Finish building the transaction.","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Fill-in the psbt::Output::redeem_script and …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Only spend utxos added by add_utxo.","Use a specific nLockTime while creating the transaction","Only spend change outputs","Only Fill-in the psbt::Input::witness_utxo field when …","Choose the ordering for inputs and outputs of the …","","","Set the policy path to use while creating the transaction …","Replace the recipients already added with a new list","Sign with a specific sig hash","Sort transaction inputs and outputs by TxOrdering variant","","","","","","","","","","","","","","","","","","","","","Replace the internal list of unspendable utxos with a new …","Build a transaction with a specific version","","","","",""],"i":[17,17,17,17,17,0,1,0,17,17,17,12,17,0,17,1,17,17,17,17,0,12,0,17,17,17,17,17,17,17,0,17,17,17,0,17,0,17,0,0,0,0,1,1,3,1,17,1,3,10,11,12,13,17,1,3,10,11,12,13,0,1,1,3,10,11,12,13,1,3,10,11,12,13,1,13,10,13,3,3,10,0,0,1,10,13,1,3,10,11,12,13,13,3,3,17,17,1,3,10,11,12,13,0,17,17,17,17,17,17,17,17,1,3,10,11,12,13,3,3,3,3,3,3,1,10,17,1,3,10,11,12,13,10,10,0,12,10,1,3,13,17,0,13,11,13,1,10,13,0,3,0,1,3,10,11,12,13,17,13,17,1,3,10,11,12,13,17,1,3,10,11,12,13,13,12,10,17,1,3,10,11,12,13,11,168,0,17,1,3,10,11,12,13,0,1,169,169,170,171,172,172,34,0,0,0,0,0,0,0,45,0,0,58,0,0,0,45,34,0,0,0,34,40,0,34,45,0,34,34,40,34,46,47,38,34,44,45,34,46,47,38,44,45,34,46,47,38,38,0,58,46,47,58,47,58,58,46,47,58,46,47,58,58,46,47,58,46,47,0,44,45,34,46,47,38,44,45,34,46,47,38,44,45,34,46,47,38,38,44,34,34,34,34,34,38,34,38,44,45,34,46,47,38,0,34,38,38,173,34,38,34,44,45,34,34,46,47,38,38,34,38,44,45,34,34,34,34,34,34,34,46,47,38,38,34,38,38,38,34,38,38,38,34,34,38,38,34,44,45,34,46,47,38,44,45,34,46,47,38,38,142,68,34,38,38,38,34,38,38,44,58,46,47,38,34,38,58,46,47,34,34,34,34,34,34,34,34,34,34,34,34,34,34,38,44,58,38,34,38,38,44,45,34,46,47,38,58,46,47,0,38,34,38,34,38,38,34,34,38,34,38,58,46,47,0,44,45,34,46,47,38,34,38,34,58,58,34,38,44,45,34,46,47,38,44,45,34,46,47,38,38,44,45,34,46,47,38,34,44,45,34,46,47,38,44,38,44,0,0,0,0,22,22,0,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,83,23,23,0,84,0,0,83,82,0,83,83,23,23,23,83,84,56,23,84,84,0,0,0,56,56,82,83,83,0,0,83,83,83,82,82,83,84,57,85,23,56,82,83,84,57,85,23,56,82,83,84,57,85,56,82,83,84,57,85,56,57,85,85,82,83,84,57,85,23,82,83,84,57,85,23,23,56,82,83,84,84,57,57,85,23,56,57,82,85,83,57,82,83,84,57,85,23,56,83,84,85,57,85,23,57,57,82,83,84,57,85,85,82,83,84,57,85,56,23,82,83,84,57,85,23,56,82,83,84,57,85,23,56,82,83,84,57,85,23,56,82,83,84,57,85,23,56,174,174,174,175,176,177,176,177,176,177,176,177,176,177,178,179,180,181,182,183,183,182,184,185,0,0,0,0,0,0,0,0,0,0,0,89,90,91,93,94,95,96,97,98,89,90,91,93,94,95,96,97,98,186,89,90,91,93,94,95,96,97,98,89,90,91,93,94,95,96,97,98,89,90,91,93,94,95,96,97,98,87,89,90,91,93,94,95,96,97,98,89,90,91,93,94,95,96,97,98,89,90,91,93,94,95,96,97,98,89,90,91,93,94,95,96,97,98,89,90,91,93,94,95,96,97,98,25,0,0,0,0,187,187,0,0,105,0,0,0,0,25,25,25,58,0,0,37,25,25,187,111,0,111,0,0,37,40,108,0,0,0,0,37,0,105,108,40,0,188,40,111,101,107,37,102,25,103,40,108,104,109,105,111,101,107,37,102,25,103,40,108,104,109,105,58,58,58,58,58,58,58,58,101,37,102,103,40,104,105,101,37,102,103,40,104,105,103,40,104,105,102,102,101,40,103,37,103,40,104,105,107,37,102,25,25,103,103,40,40,108,108,104,109,105,103,111,111,111,101,107,37,102,25,25,25,103,40,40,108,104,109,105,107,107,40,108,103,40,187,189,187,189,111,40,103,40,104,105,111,101,107,37,102,25,103,40,108,104,109,105,88,92,101,101,107,40,108,92,111,101,101,111,111,40,188,37,188,37,188,37,40,40,103,104,109,103,0,40,58,103,103,0,58,103,104,109,58,107,103,40,104,105,58,103,25,103,103,103,58,103,0,101,37,102,103,40,104,105,108,25,103,40,108,58,58,103,111,101,107,37,102,25,103,40,108,104,109,105,111,101,107,37,102,25,103,40,108,104,109,105,111,101,107,37,102,25,103,40,108,104,109,105,111,101,107,37,102,25,103,40,108,104,109,105,0,190,190,190,0,0,0,135,0,134,134,0,134,135,0,0,0,116,117,131,117,117,117,117,117,116,117,134,131,135,116,117,134,131,135,117,117,117,117,116,116,0,117,116,116,131,117,117,117,116,116,131,0,117,116,116,117,134,131,131,135,135,116,117,134,131,135,117,117,117,117,117,117,117,117,116,131,117,117,116,117,134,131,135,191,117,131,117,117,117,117,117,117,117,117,117,135,117,117,116,117,0,117,117,117,116,116,131,135,116,117,116,116,116,117,134,131,135,116,117,134,131,135,0,116,117,134,131,135,116,116,117,134,131,135,0,0,150,0,0,0,0,0,150,0,150,149,146,147,148,150,149,146,147,148,146,147,148,146,147,148,161,146,147,148,0,146,147,148,149,149,150,149,146,147,148,150,149,146,147,148,150,149,146,147,148,149,148,149,149,146,147,148,150,149,146,147,148,150,149,146,147,148,150,149,146,147,148,150,149,146,147,148,192,193,193,192,193,0,0,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,157,152,157,152,157,24,0,24,24,24,154,24,24,24,24,24,24,157,152,154,24,0,0,0,0,0,0,0,0,154,0,0,24,55,133,133,55,133,152,24,154,156,118,55,133,157,152,24,154,156,118,55,133,157,55,152,24,154,156,118,55,133,157,152,24,154,156,118,55,133,157,152,118,118,55,133,157,156,194,156,156,152,24,154,118,157,55,152,24,24,154,156,118,55,133,157,152,152,152,24,24,154,156,118,55,133,157,152,194,156,156,55,152,24,154,156,118,55,133,157,156,55,152,118,24,55,133,195,156,156,119,156,133,55,133,152,24,154,156,118,55,133,157,24,133,133,152,24,154,156,118,55,133,157,152,24,154,156,118,55,133,157,152,24,154,156,118,55,133,157,152,24,154,156,118,55,133,157,196,164,0,163,163,0,0,163,164,0,0,0,164,128,128,128,128,128,128,128,128,128,129,127,128,164,163,129,127,128,164,163,128,129,127,128,164,163,129,127,128,164,163,164,163,128,128,129,127,164,163,128,128,128,128,128,164,163,128,128,128,129,127,128,164,163,129,127,128,164,163,164,163,128,129,127,128,164,163,128,128,128,128,128,164,163,128,128,128,164,129,127,128,164,163,129,127,128,164,163,129,127,128,164,163,129,127,128,164,163,128,128,129,127,128,164,163],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[1,2],[1],[3,4],[[],5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],[[9,[[8,[6,7]]]]]],[1,1],[3,3],[10,10],[11,11],[12,12],[13,13],[[]],[[]],[[]],[[]],[[]],[[]],[[1,1],14],[[13,13],14],0,0,[[],3],[[],3],0,0,0,[[],[[9,[1]]]],[[],[[9,[10]]]],[[],[[9,[13]]]],[[1,1],15],[[3,3],15],[[10,10],15],[[11,11],15],[[12,12],15],[[13,13],15],0,[[3,5],16],[[3,5],16],[[17,18],19],[[17,18],19],[[1,18],19],[[3,18],19],[[10,18],19],[[11,18],19],[[12,18],19],[[13,18],19],0,[20,17],[21,17],[[]],[22,17],[23,17],[24,17],[25,17],[26,17],[[]],[[]],[[]],[[]],[[]],[[]],[4,3],[4,3],[4,3],[4,3],[[16,5],3],[[16,5],3],[1],[10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,[12,27],0,[[1,1],[[28,[14]]]],[[3,3],[[28,[14]]]],[[13,13],[[28,[14]]]],[29],0,0,0,0,[1,9],[10,9],[13,9],0,[[3,3]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],30],0,[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],0,[12,31],0,[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],0,[[],5],[[],33],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],9],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[34,35],[[9,[36,26]]]],[[],37],[[],37],[38,39],[[[34,[40]],41],[[34,[42]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[38,[[8,[38,7]]]],0,[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[39,[[9,[43]]]],[39,[[9,[43]]]],[39,[[9,[43]]]],[[],[[9,[43]]]],[[],[[9,[43]]]],[[],[[9,[43]]]],0,[44,44],[45,45],[34,34],[46,46],[47,47],[38,38],[[]],[[]],[[]],[[]],[[]],[[]],[[44,44],14],[[45,45],14],[[34,34],14],[[46,46],14],[[47,47],14],[[38,38],14],[38,15],0,[[[34,[40]],41],[[34,[42]]]],[[[34,[40]],48,41],[[9,[[34,[49]],50]]]],[[[34,[42]],48],[[9,[[34,[49]],50]]]],[34,51],[[],[[9,[34]]]],[[],[[9,[38]]]],[[[34,[40]]],16],[38,52],[[44,44],15],[[45,45],15],[[34,34],15],[[46,46],15],[[47,47],15],[[38,38],15],0,[34,[[9,[52,26]]]],0,[[38,53],[[9,[54]]]],[[55,56,48],[[9,[[28,[57]],22]]]],[[[34,[40]],55,56,48],[[9,[[28,[57]],22]]]],[[[38,[40,58]],55,56,48],[[9,[[28,[57]],22]]]],[[[34,[40]],48,52,[59,[41]]],[[9,[28,50]]]],[[44,18],[[9,[60]]]],[[45,18],[[9,[60]]]],[[34,18],[[9,[60]]]],[[34,18],[[9,[60]]]],[[46,18],[[9,[60]]]],[[47,18],[[9,[60]]]],[[38,18],[[9,[60]]]],[[38,18],[[9,[60]]]],[34,15],[38,15],[[]],[[]],[61,34],[[]],[62,34],[63,34],[64,34],[65,34],[66,34],[[]],[[]],[[]],[39,[[9,[38,26]]]],[33,[[9,[34,26]]]],[33,[[9,[38,26]]]],[[33,53],[[9,[38,26]]]],[33,[[9,[38,26]]]],[67,[[9,[34,26]]]],[67,[[9,[38,26]]]],[[38,5],[[28,[38]]]],[[38,5],28],[34,[[9,[26]]]],[34,[[9,[26]]]],[38,15],[38,15],[[[34,[40]]],15],[44],[45],[34],[46],[47],[38],[[]],[[]],[[]],[[]],[[]],[[]],[38,39],[[48,35],[[9,[22]]]],[[68,48,35],[[9,[22]]]],[[[34,[40]]],15],[38,15],[38,69],[38,70],[34,[[9,[71,26]]]],[38,[[9,[71,26]]]],[38,[[9,[72]]]],[[44,48],[[28,[73]]]],[38,[[28,[5]]]],[38,[[28,[5]]]],[38,[[28,[5]]]],[38,[[9,[5,26]]]],[34,[[9,[5,26]]]],[38,[[9,[5,26]]]],[[],33],[[],33],[[],33],[[[38,[74]]],[[9,[34,26]]]],[[],34],[[],34],[[[38,[46]]],[[9,[34,26]]]],[[5,[8,[7]]],[[9,[34,26]]]],[65,34],[61,34],[[],[[9,[34,26]]]],[[[38,[47]]],[[9,[34,26]]]],[[5,[8,[7]]],[[9,[34,26]]]],[[[28,[75]]],[[9,[34,26]]]],[[],[[9,[34,26]]]],[[[38,[47]]],[[9,[34,26]]]],[[5,[8,[7]]],[[9,[34,26]]]],0,0,[38,[[9,[26]]]],[52,[[9,[38,26]]]],[[48,33],[[9,[26]]]],[52,[[9,[38,26]]]],[[52,53],[[9,[38,26]]]],[[44,44],[[28,[14]]]],[[45,45],[[28,[14]]]],[[34,34],[[28,[14]]]],[[46,46],[[28,[14]]]],[[47,47],[[28,[14]]]],[[38,38],[[28,[14]]]],[[],5],[[],5],[[],5],0,[38,15],[34,[[9,[26]]]],[38,[[9,[54]]]],[[34,76],[[9,[26]]]],[38,[[9,[[8,[[8,[2,7]],7]],26]]]],[38,[[9,[[8,[[8,[2,7]],7]],26]]]],[34,[[9,[52,26]]]],[34,52],[38,5],[34,9],[38,9],[[],77],[[],77],[[],77],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],30],[[],30],[[[34,[40]],78],30],[38,[[9,[26]]]],[38,[[9,[26]]]],[34,9],[38,9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],0,[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[34,52],[[]],[[]],[[]],[[]],[[]],[[]],0,[38,15],0,[33,[[9,[30,22]]]],[33,[[9,[22]]]],[33,[[9,[30,22]]]],[33,[[9,[22]]]],0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[22,18],19],[[22,18],19],[[]],[23,22],[79,22],[25,22],[80,22],[26,22],[81,22],[21,22],[[]],[29],[[],30],[[],9],[[],9],[[],32],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[82,82],[83,83],[84,84],[57,57],[85,85],[56,56],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],85],[[82,82],15],[[83,83],15],[[84,84],15],[[57,57],15],[[85,85],15],[[23,23],15],[[82,18],19],[[83,18],19],[[84,18],19],[[57,18],19],[[85,18],19],[[23,18],19],[[23,18],19],[[56,18],19],[[]],[[]],[15,84],[[]],[[]],[83,57],[[]],[[]],[[]],[[57,86],[[9,[85,23]]]],[82],[85],[83,30],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[83,15],[84,15],[85,15],0,[[85,85],[[28,[14]]]],[29],[57,15],0,[82,9],[83,9],[84,9],[57,9],[85,9],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],30],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[35,[[9,[87,22]]]],[[[89,[[88,[46]]]],35],[[9,[87,22]]]],[[[90,[[88,[47]]]],35],[[9,[87,22]]]],[[[91,[[88,[47]]]],35],[[9,[87,22]]]],[[[93,[[92,[46]]]],35],[[9,[87,22]]]],[[[94,[[92,[46]]]],35],[[9,[87,22]]]],[[[95,[[92,[47]]]],35],[[9,[87,22]]]],[[[96,[[92,[47]]]],35],[[9,[87,22]]]],[[[97,[[92,[47]]]],35],[[9,[87,22]]]],[[[98,[[92,[47]]]],35],[[9,[87,22]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[87,48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[48,35],[[9,[22]]]],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[],99],[[],37],[[40,41],42],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[38,[[9,[43]]]],[39,[[9,[43]]]],[[],[[9,[43]]]],[[[101,[100,58]]],[[101,[100,58]]]],[37,37],[102,102],[103,103],[40,40],[104,104],[105,105],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[103,103],14],[[40,40],14],[[104,104],14],[[105,105],14],0,[[],102],[[[101,[58]]]],[[40,41],42],[103,52],[[37,37],15],[[103,103],15],[[40,40],15],[[104,104],15],[[105,105],15],[[[107,[[0,[106,58]]]],18],19],[[37,18],19],[[102,18],19],[[25,18],19],[[25,18],19],[[103,18],[[9,[60]]]],[[103,18],[[9,[60]]]],[[40,18],[[9,[60]]]],[[40,18],[[9,[60]]]],[[108,18],[[9,[60]]]],[[108,18],[[9,[60]]]],[[104,18],[[9,[60]]]],[[109,18],[[9,[60]]]],[[105,18],[[9,[60]]]],[103,15],[110,[[111,[58]]]],[112,[[111,[58]]]],[[]],[[]],[[]],[[]],[[]],[26,25],[[]],[21,25],[[]],[42,40],[[]],[[]],[[]],[[]],[[]],[[40,99],[[107,[58]]]],[[108,99],[[107,[58]]]],[33,[[9,[40]]]],[33,[[9,[108]]]],[67,[[9,[103,26]]]],[40,73],[[],[[9,[101]]]],[[],[[9,[101]]]],[[],[[9,[101]]]],[[],[[9,[101]]]],[[[111,[58]]],15],[40,15],[103],[40],[104],[105],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[[9,[107,25]]]],[[[28,[113]],73],[[9,[107,25]]]],[[101,[28,[113]],73],[[9,[107,25]]]],[101,[[9,[107,25]]]],[[[107,[58]]],[[9,[[107,[58]],25]]]],[40,[[9,[[107,[58]],25]]]],[108,[[9,[[107,[58]],25]]]],[[],[[9,[111,25]]]],[[[111,[58]]],[[9,[[111,[58]],25]]]],[101,[[9,[111,25]]]],[[[101,[58]]]],[[[111,[58]],35],[[28,[112]]]],[[[111,[58]],35,48],110],[40,15],[[],15],[37,15],[[],15],[37,15],[[],15],[37,15],[40,15],[40,15],0,0,0,[103,[[9,[71,26]]]],[[],99],[40,114],[38,[[28,[5]]]],[103,5],[103,5],[[99,99],99],[[],33],[[5,[8,[7]]],[[9,[103,26]]]],0,0,[38,[[9,[26]]]],[[[107,[58]],99],[[107,[58]]]],[[103,103],[[28,[14]]]],[[40,40],[[28,[14]]]],[[104,104],[[28,[14]]]],[[105,105],[[28,[14]]]],[[],5],0,[29],[103,[[9,[26]]]],[103,[[9,[[8,[[8,[2,7]],7]],26]]]],[103,5],[[],77],[103,39],[[],99],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[108,48],[[9,[40,115]]]],[[],30],[[],30],[[],30],[[],30],[38,[[9,[26]]]],[38,[[9,[26]]]],[103,[[9,[103]]]],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],[[28,[16]]]],[[],[[28,[3]]]],[5,[[28,[31]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,[[116,116],116],[[117,1,118,[120,[119]]]],0,[[117,121],[[9,[122]]]],[117,123],[117,124],[117,124],[117,123],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[117,125],[[9,[[128,[126,127]],17]]]],[117,[[128,[126,129]]]],[[117,130]],[117,86],[116,116],[[]],0,[117,9],0,[[],116],[131],[[117,1],[[28,[41]]]],[[117,52],28],[[117,1],30],[[],[[9,[116]]]],[[116,116],15],[[131,131],15],0,[[117,132,133],[[9,[15,17]]]],[[116,18],[[9,[60]]]],[[116,18],[[9,[60]]]],[[[117,[106]],18],19],[[134,18],19],[[131,18],19],[[131,18],19],[[[135,[106]],18],19],[[135,18],19],[[]],[[]],[[]],[[]],[[]],[[117,134],131],[117,116],[[117,1],68],[[117,134],131],[[117,10,[28,[136]],15],[[9,[137,17]]]],[[117,1],[[120,[55]]]],[[117,125,15],[[28,[13]]]],[[117,27],[[28,[10]]]],0,0,[[117,138],[[9,[15,139]]]],[[117,130,140],[[9,[15,[141,[140]]]]]],[[]],[[]],[[]],[[]],[[]],[52,15],[[117,52],15],0,[117,86],[117,[[28,[138]]]],[[117,15],[[8,[13]]]],[117,[[8,[10]]]],[117,35],[[142,[28,[142]],35],[[9,[117,135]]]],[[142,[28,[142]],35],[[9,[117,22]]]],[[117,1],41],[[117,1],[[9,[[28,[57]],17]]]],[29],[[117,1],[[28,[68]]]],[117,48],[116,9],[[117,132,133],[[9,[15,17]]]],0,[117,[[86,[1,[0,[143,100]]]]]],[[117,1],[[0,[143,100]]]],[117,144],[[]],[[],30],[[],30],[[],30],[116,16],[117,145],0,[116,16],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],0,[[],32],[[],32],[[],32],[[],32],[[],32],0,[[]],[[]],[[]],[[]],[[]],[[28,35,48],[[9,[30,17]]]],0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[146,146],[147,147],[148,148],[[]],[[]],[[]],[[[8,[11]],[8,[11]],3,16,52],[[9,[149,17]]]],[[146,[8,[11]],[8,[11]],3,16,52],[[9,[149,17]]]],[[147,[8,[11]],[8,[11]],3,16,52],[[9,[149,17]]]],[[148,[8,[11]],[8,[11]],3,16,52],[[9,[149,17]]]],[[16,3,52],150],[[],146],[[],147],[[],148],0,0,[[150,18],19],[[149,18],19],[[146,18],19],[[147,18],19],[[148,18],19],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[149,16],[16,148],0,[149,16],[[]],[[]],[[]],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],32],[[],32],[[],32],[[],32],[[],32],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,[[]],[[]],[151,[[28,[30]]]],[151,30],[[],[[9,[151]]]],[[117,33,15],[[9,[151,33]]]],[[151,18],19],[[]],[33,[[9,[151]]]],[[]],0,[151,9],[151,30],[[],9],[[],9],[[],32],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[55,152,118,[120,[119]]],[[28,[[120,[119]]]]]],0,0,[[55,48],153],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[153,34,48],55],[152,152],[24,24],[154,154],[[[156,[[0,[100,155,106,100]]]]],[[156,[[0,[100,155,106,100]]]]]],[118,118],[55,55],[133,133],[157,157],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[152,152],14],[[118,118],14],[[],118],[[],55],[[],133],[[],157],[[[156,[[0,[155,106,100]]]]]],[[],[[28,[108]]]],[[[156,[158]]],[[28,[108]]]],[[[156,[[44,[112]]]]],[[28,[108]]]],[[152,152],15],[[24,24],15],[[154,154],15],[[118,118],15],[[157,157],15],[[55,152],[[28,[120]]]],[[152,18],19],[[24,18],19],[[24,18],19],[[154,18],19],[[[156,[[0,[106,155,106,100]]]],18],19],[[118,18],19],[[55,18],19],[[133,18],19],[[157,18],19],[114,152],[159,152],[[]],[160,24],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[152],[48,152],[[[156,[158]],48],152],[[[156,[[44,[112]]]],48],152],[55,[[8,[152]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[0,[155,106,100]],154],[[156,[[0,[155,106,100]]]]]],[[],55],[[152,152],[[28,[14]]]],[[118,118],[[28,[14]]]],[29],[[55,152,118],[[28,[[120,[119]]]]]],0,[[132,5,133,48],[[9,[24]]]],[[[156,[158]],132,5,133,48],[[9,[24]]]],[[[156,[[44,[112]]]],132,5,133,48],[[9,[24]]]],[[132,133,48],[[9,[24]]]],[[132,133,48],[[9,[24]]]],0,[55,[[8,[120]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],30],0,0,[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,[[[128,[161,129]]],[[128,[161,129]]]],[[[128,[161,162]],27,137,5],[[9,[[128,[161,162]],17]]]],[[[128,[161,162]]],[[128,[161,162]]]],[[[128,[161,129]],52,16],[[128,[161,129]]]],[[[128,[161,162]],27],[[128,[161,162]]]],[[[128,[161,162]],27],[[9,[[128,[161,162]],17]]]],[[[128,[161,162]]],[[9,[[128,[161,162]],17]]]],[[[128,[161,162]],15],[[128,[161,162]]]],[[[128,[126,127]],52],[[9,[[128,[126,127]],17]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[128,[161,162]],163],[[128,[161,162]]]],[129,129],[127,127],[[[128,[100]]],[[128,[100]]]],[164,164],[163,163],[[]],[[]],[[]],[[]],[[]],[[164,164],14],[[163,163],14],[[[128,[161,162]],161],[[128,[161,162]]]],[[[128,[161,162]],41],[[128,[161,162]]]],[[],129],[[],127],[[],164],[[],163],[[[128,[161,162]]],[[128,[161,162]]]],[[[128,[161,129]],52],[[128,[161,129]]]],[[[128,[161,162]]],[[128,[161,162]]]],[[[128,[161,162]]],[[128,[161,162]]]],[[[128,[161,162]],165],[[128,[161,162]]]],[[164,164],15],[[163,163],15],[[[128,[161,162]],16],[[128,[161,162]]]],[[[128,[161,162]],3],[[128,[161,162]]]],[[[128,[161,162]]],[[9,[17]]]],[[129,18],19],[[127,18],19],[[[128,[106,106,106]],18],19],[[164,18],19],[[163,18],19],[[]],[[]],[[]],[[]],[[]],[164],[163],[[[128,[161,162]]],[[128,[161,162]]]],[[]],[[]],[[]],[[]],[[]],[[[128,[161,162]]],[[128,[161,162]]]],[[[128,[161,162]],166],[[128,[161,162]]]],[[[128,[161,162]]],[[128,[161,162]]]],[[[128,[161,162]]],[[128,[161,162]]]],[[[128,[161,162]],164],[[128,[161,162]]]],[[164,164],[[28,[14]]]],[[163,163],[[28,[14]]]],[[[128,[161,162]],[86,[30,[8,[5]]]],1],[[128,[161,162]]]],[[[128,[161,129]],8],[[128,[161,129]]]],[[[128,[161,162]],136],[[128,[161,162]]]],[[164,130]],[[]],[[]],[[]],[[]],[[]],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],9],[[],32],[[],32],[[],32],[[],32],[[],32],[[[128,[161,162]],[8,[27]]],[[128,[161,162]]]],[[[128,[161,162]],167],[[128,[161,162]]]],[[]],[[]],[[]],[[]],[[]]],"p":[[4,"KeychainKind"],[15,"u8"],[3,"FeeRate"],[15,"f32"],[15,"usize"],[3,"u5"],[3,"Global"],[3,"Vec"],[4,"Result"],[3,"LocalUtxo"],[3,"WeightedUtxo"],[4,"Utxo"],[3,"TransactionDetails"],[4,"Ordering"],[15,"bool"],[15,"u64"],[4,"Error"],[3,"Formatter"],[6,"Result"],[4,"Error"],[4,"Error"],[4,"Error"],[4,"PolicyError"],[4,"SignerError"],[4,"KeyError"],[4,"Error"],[3,"OutPoint"],[4,"Option"],[3,"Demand"],[3,"String"],[3,"TxOut"],[3,"TypeId"],[15,"str"],[4,"Descriptor"],[4,"Network"],[3,"Address"],[4,"ScriptContextEnum"],[3,"Miniscript"],[4,"Terminal"],[4,"DescriptorPublicKey"],[15,"u32"],[3,"DefiniteDescriptorKey"],[4,"ScriptContextError"],[3,"DescriptorXKey"],[4,"Wildcard"],[4,"Legacy"],[4,"Segwitv0"],[3,"Secp256k1"],[3,"PublicKey"],[4,"ConversionError"],[4,"DescriptorType"],[3,"Script"],[3,"ExtParams"],[4,"AnalysisError"],[3,"SignersContainer"],[4,"BuildSatisfaction"],[3,"Policy"],[8,"ScriptContext"],[3,"Range"],[3,"Error"],[3,"Wsh"],[3,"Bare"],[3,"Sh"],[3,"Tr"],[3,"Wpkh"],[3,"Pkh"],[3,"Tree"],[6,"ExtendedDescriptor"],[3,"Iter"],[3,"PkIter"],[4,"Policy"],[4,"LiftError"],[3,"DerivationPath"],[4,"BareCtx"],[4,"TapTree"],[3,"TxIn"],[4,"SigType"],[3,"HashMap"],[4,"Error"],[4,"Error"],[4,"Error"],[4,"PkOrF"],[4,"SatisfiableItem"],[4,"Satisfaction"],[3,"Condition"],[3,"BTreeMap"],[6,"DescriptorTemplateOut"],[8,"IntoDescriptorKey"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[8,"DerivableKey"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[6,"ValidNetworks"],[8,"Clone"],[3,"GeneratedKey"],[3,"PrivateKeyGenerateOptions"],[3,"SortedMultiVec"],[3,"SinglePub"],[4,"SinglePubKey"],[8,"Debug"],[4,"DescriptorKey"],[4,"DescriptorSecretKey"],[3,"SinglePriv"],[3,"ExtendedPubKey"],[4,"ExtendedKey"],[3,"ExtendedPrivKey"],[6,"KeySource"],[3,"Fingerprint"],[3,"DescriptorKeyParseError"],[3,"Balance"],[3,"Wallet"],[3,"SignerOrdering"],[8,"TransactionSigner"],[3,"Arc"],[6,"Update"],[6,"UpdateError"],[3,"ChainGraph"],[3,"TxGraph"],[3,"Txid"],[6,"DefaultCoinSelectionAlgorithm"],[3,"BumpFee"],[3,"TxBuilder"],[3,"CreateTx"],[3,"Transaction"],[3,"AddressInfo"],[3,"PartiallySignedTransaction"],[3,"SignOptions"],[4,"AddressIndex"],[4,"NewError"],[3,"PsbtSighashType"],[3,"Input"],[3,"BlockId"],[4,"InsertCheckpointError"],[4,"ConfirmationTime"],[4,"InsertTxError"],[8,"IntoWalletDescriptor"],[8,"Iterator"],[3,"KeychainChangeSet"],[8,"DoubleEndedIterator"],[3,"LargestFirstCoinSelection"],[3,"OldestFirstCoinSelection"],[3,"BranchAndBoundCoinSelection"],[3,"CoinSelectionResult"],[4,"Excess"],[3,"FullyNodedExport"],[4,"SignerId"],[6,"KeyMap"],[4,"SignerContext"],[8,"Sized"],[3,"SignerWrapper"],[4,"TapLeavesOptions"],[3,"PrivateKey"],[3,"Hash"],[4,"Error"],[8,"CoinSelectionAlgorithm"],[8,"TxBuilderContext"],[4,"ChangeSpendPolicy"],[4,"TxOrdering"],[3,"Sequence"],[4,"LockTime"],[15,"i32"],[8,"Vbytes"],[13,"InsufficientFunds"],[13,"FeeRateTooLow"],[13,"FeeTooLow"],[13,"Foreign"],[8,"ExtractPolicy"],[13,"PsbtTimelocks"],[13,"Complete"],[13,"Partial"],[13,"PartialComplete"],[13,"Sha256Preimage"],[13,"Hash256Preimage"],[13,"Ripemd160Preimage"],[13,"Hash160Preimage"],[13,"Thresh"],[13,"Multisig"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[8,"DescriptorTemplate"],[8,"GeneratableKey"],[8,"ExtScriptContext"],[8,"GeneratableDefaultOptions"],[8,"PsbtUtils"],[8,"IsDust"],[13,"Change"],[13,"NoChange"],[8,"SignerCommon"],[8,"InputSigner"],[13,"Tap"]]},\ +"bdk_chain":{"doc":"This crate is a collection of core structures for Bitcoin …","t":[3,17,4,13,13,8,8,3,3,4,13,13,11,2,11,11,11,11,11,11,11,11,11,11,0,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,12,11,11,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,0,11,11,11,11,11,2,11,12,11,11,11,11,11,11,11,11,11,11,0,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,13,13,3,3,13,6,4,13,4,3,13,13,4,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,12,12,17,3,3,3,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,12,11,12,11,11,11,11,11,11,16,3,8,16,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,8,3,13,4,4,13,3,13,13,13,4,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,12,11,11,11,11,11,11,11,11,11,11],"n":["BlockId","COINBASE_MATURITY","ConfirmationTime","Confirmed","Confirmed","DescriptorExt","ForEachTxOut","FullTxOut","SpkTxOutIndex","TxHeight","Unconfirmed","Unconfirmed","all_spks","bitcoin","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain_graph","chain_position","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","default","default","default","deserialize","deserialize","deserialize","dust_value","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","for_each_txout","from","from","from","from","from","from","from","from","hash","hash","hash","height","height","height","index_of_spk","insert_spk","into","into","into","into","into","is_confirmed","is_confirmed","is_mature","is_on_coinbase","is_relevant","is_spendable_at","is_used","keychain","mark_used","max_ord_of_height","max_ord_of_height","min_ord_of_height","min_ord_of_height","miniscript","net_value","outpoint","outputs_in_range","partial_cmp","partial_cmp","partial_cmp","scan","scan_txout","sent_and_received","serialize","serialize","serialize","sparse_chain","spent_by","spk_at_index","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","tx_graph","txout","txout","txouts","txouts_in_tx","type_id","type_id","type_id","type_id","type_id","unmark_used","unused_spks","vzip","vzip","vzip","vzip","vzip","height","time","Chain","Chain","ChainGraph","ChangeSet","Conflict","InsertCheckpointError","InsertTxError","Missing","NewError","UnresolvableConflict","UnresolvableConflict","UnresolvableConflict","UpdateError","already_confirmed_tx","append","apply_changeset","apply_update","as_ref","as_ref","as_ref","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain","chain","checkpoint_limit","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","contains_eviction","default","default","deserialize","determine_changeset","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_txout","for_each_txout","from","from","from","from","from","from","from","from","from","from","full_txout","get_tx_in_chain","graph","graph","inflate_update","insert_checkpoint","insert_checkpoint_preview","insert_tx","insert_tx_preview","insert_txout","insert_txout_preview","into","into","into","into","into","into","invalidate_checkpoints","invalidate_checkpoints_preview","is_empty","is_empty","new","provide","provide","provide","provide","serialize","set_checkpoint_limit","spent_by","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","transactions_in_chain","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","tx_conflicts_in_chain","type_id","type_id","type_id","type_id","type_id","type_id","update_tx","vzip","vzip","vzip","vzip","vzip","vzip","a","b","BIP32_MAX_INDEX","Balance","DerivationAdditions","KeychainChangeSet","KeychainScan","KeychainTracker","KeychainTxOutIndex","add","add_keychain","add_keychain","append","append","apply_additions","apply_changeset","apply_update","as_inner","as_ref","as_ref","as_ref","as_ref","as_ref","balance","balance_at","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain","chain_graph","chain_graph","checkpoint_limit","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","confirmed","default","default","default","default","default","default","deref","derivation_indices","deserialize","deserialize","deserialize","determine_changeset","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_txout","from","from","from","from","from","from","from","from","from","full_txouts","full_utxos","graph","immature","inner","insert_checkpoint","insert_checkpoint_preview","insert_tx","insert_tx_preview","into","into","into","into","into","into","is_empty","is_empty","keychains","keychains","last_active_indices","last_revealed_index","last_revealed_indices","last_used_index","last_used_indices","lookahead_to_target","lookahead_to_target_multi","lookaheads","mark_used","next_index","next_unused_spk","persist","reveal_next_spk","reveal_to_target","reveal_to_target_multi","revealed_spks_of_all_keychains","revealed_spks_of_keychain","scan","scan_txout","serialize","serialize","serialize","set_checkpoint_limit","set_lookahead","set_lookahead_for_all","spks_of_all_keychains","spks_of_keychain","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","total","trusted_pending","trusted_spendable","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","txout_index","txouts_of_keychain","type_id","type_id","type_id","type_id","type_id","type_id","unmark_used","untrusted_pending","unused_spks_of_keychain","update","vzip","vzip","vzip","vzip","vzip","vzip","LoadError","Persist","PersistBackend","WriteError","append_changeset","borrow","borrow_mut","commit","fmt","from","into","load_into_keychain_tracker","new","stage","staged","try_from","try_into","type_id","vzip","ChainPosition","ChangeSet","HashNotMatching","InsertCheckpointError","InsertTxError","NotConnected","SparseChain","TxInconsistent","TxMovedUnexpectedly","TxTooHigh","UpdateError","append","apply_changeset","apply_update","as_ref","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","changeset_additions","checkpoint_at","checkpoint_limit","checkpoints","checkpoints","clear_mempool","clear_mempool_preview","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","default","default","deserialize","determine_changeset","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from_checkpoints","full_txout","height","initial_changeset","insert_checkpoint","insert_checkpoint_preview","insert_tx","insert_tx_preview","into","into","into","into","into","invalidate_checkpoints","invalidate_checkpoints_preview","is_empty","is_empty","latest_checkpoint","max_ord_of_height","min_ord_of_height","provide","provide","provide","range_checkpoints","range_txids","range_txids_by_height","range_txids_by_position","serialize","set_checkpoint_limit","spent_by","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","tx_position","txids","txids","type_id","type_id","type_id","type_id","type_id","unconfirmed","vzip","vzip","vzip","vzip","vzip","height","original_hash","update_hash","original_pos","tip_height","tx_height","txid","txid","update_pos","original_pos","txid","update_pos","Additions","TxDescendants","TxGraph","all_txouts","append","apply_additions","apply_update","as_ref","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","calculate_fee","checked_sum","checked_sum","clone","clone","clone_into","clone_into","default","default","deserialize","determine_additions","direct_conflicts_of_tx","eq","eq","fmt","fmt","for_each_txout","for_each_txout","from","from","from","full_transactions","get_tx","get_txout","insert_tx","insert_tx_preview","insert_txout","insert_txout_preview","into","into","into","into_iter","is_empty","is_empty","new","next","outspends","partial_transactions","serialize","to_owned","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","tx","tx_outspends","txout","txouts","txouts","type_id","type_id","type_id","vzip","vzip","vzip","walk_conflicts","walk_descendants"],"q":["bdk_chain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::ConfirmationTime","","bdk_chain::chain_graph","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::chain_graph::NewError","","bdk_chain::keychain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::keychain::persist","","","","","","","","","","","","","","","","","","","bdk_chain::sparse_chain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::sparse_chain::InsertCheckpointError","","","bdk_chain::sparse_chain::InsertTxError","","","","","","bdk_chain::sparse_chain::UpdateError","","","bdk_chain::tx_graph","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["A reference to a block in the cannonical chain.","How many confirmations are needed for a coinbase output to …","Block height and timestamp in which a transaction is …","","","A trait to extend the functionality of a miniscript …","Trait to do something with every txout contained in a …","A TxOut with as much data as we can retreive about it","An index storing TxOuts that have a script pubkey that …","Represents the height in which a transaction is confirmed …","","","The script pubkeys being tracked by the index.","","","","","","","","","","","","Module for structures that combine the features of …","The position of the transaction in outpoint in the overall …","","","","","","","","","","","","","","","","","","","","Returns the minimum value (in satoshis) that an output …","","","","","","","","","","","The provided closure f will called with each outpoint/txout…","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Returns the argument unchanged.","","","The hash of the block","","","The height the block was confirmed at","Returns the index associated with the script pubkey.","Adds a script pubkey to scan for. Returns false and does …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","Whether this output is on a coinbase transaction","Whether any of the inputs of this transaction spend a …","Whether the utxo is/was/will be spendable at height.","Returns whether the script pubkey at index has been used …","Module for keychain based structures.","Marks the script pubkey at index as used even though it …","","","","","","Computes the net value that this transaction gives to the …","The location of the TxOut","Iterates over all outputs with script pubkeys in an index …","","","","Scans an object containing many txouts.","Scan a single TxOut for a matching script pubkey, and …","Computes total input value going from script pubkeys in …","","","","Module for structures that maintain sparse (purposely …","The txid and chain position of the transaction (if any) …","Returns the script that has been inserted at the index.","","","","","","","","","","","","","","","","","Module for structures that store and traverse transactions.","Returns the txout and script pubkey index of the TxOut at …","The TxOut","Iterate over all known txouts that spend to tracked script …","Finds all txouts on a transaction that has previously been …","","","","","","Undoes the effect of mark_used. Returns whether the index …","Iterates over a unused script pubkeys in a index range.","","","","","","","","","The update chain was inconsistent with the existing chain","A consistent combination of a SparseChain<P> and a …","Represents changes to ChainGraph.","Two transactions within the sparse chain conflicted with …","A nice alias of sparse_chain::InsertCheckpointError.","Error that may occur when inserting a transaction.","One or more transactions in the chain were not in the graph","Error that may occur when calling ChainGraph::new.","Represents an unresolvable conflict between an update’s …","","A transaction in the update spent the same input as an …","Represents an update failure.","","Appends the changes in other into self such that applying …","Applies changeset to self.","Applies the update chain graph. Note this is shorthand for …","","","","","","","","","","","","","","","","Returns a reference to the internal SparseChain.","","Sets the checkpoint limit.","","","","","","","","","","","","","Returns true if this ChangeSet contains transaction …","","","","Calculates the difference between self and update in the …","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Get the full transaction output at an outpoint if it …","Get a transaction that is currently in the underlying …","Returns a reference to the internal TxGraph.","","Take an update in the form of a SparseChain<P> and attempt …","Inserts checkpoint into Self.","Determines the changes required to insert a block_id (a …","Inserts Transaction at given chain position.","Determines the changes required to insert a transaction …","Inserts a TxOut into the internal TxGraph.","Determines the changes required to insert a TxOut into the …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Invalidate checkpoints from_height (inclusive) and above. …","Determines the changes required to invalidate checkpoints …","Whether the chain graph contains any data whatsoever.","Returns true if this ChangeSet records no changes.","Create a new chain graph from a chain and a graph.","","","","","","Sets the checkpoint limit.","Finds the transaction in the chain that spends outpoint …","","","","","","","","","","","Iterate over the full transactions and their position in …","","","","","","","","","","","","","Given a transaction, return an iterator of txids that …","","","","","","","","","","","","","","","","Maximum BIP32 derivation index.","Balance differentiated in various categories.","Represents updates to the derivation index of a …","Represents changes to a KeychainTracker.","An update that includes the last active indexes of each …","A convenient combination of a KeychainTxOutIndex and a …","A convenient wrapper around SpkTxOutIndex that relates …","","Add a keychain to the tracker’s txout_index with a …","Add a keychain to the tracker’s txout_index with a …","Append another DerivationAdditions into self.","Appends the changes in other into self such that applying …","Applies the derivation additions to the KeychainTxOutIndex…","Applies the changes in changeset to KeychainTracker.","Directly applies a KeychainScan on KeychainTracker.","Get the inner map of keychain to its new derivation index.","","","","","","Returns the balance of the keychain i.e. the value of …","Returns the balance of all spendable confirmed unspent …","","","","","","","","","","","","","Returns a reference to the internal SparseChain (which is …","Returns a reference to the internal ChainGraph.","The changes that have occurred in the blockchain","Get the checkpoint limit of the internal SparseChain.","","","","","","","","","","","","","Confirmed and immediately spendable balance","","","","","","","","The changes in local keychain derivation indices","","","","Determines the resultant KeychainChangeSet if the given …","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","","Returns the argument unchanged.","Iterates through FullTxOuts that are considered to exist …","Iterates through FullTxOuts that are unspent outputs.","Returns a reference to the internal TxGraph (which is part …","All coinbase outputs not yet matured","Return a reference to the internal SpkTxOutIndex.","Directly insert a block_id into the tracker.","Determines the changes as result of inserting block_id (a …","Directly insert a transaction into the inner ChainGraph …","Determines the changes as result of inserting a …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns whether the additions are empty.","Returns whether the KeychainChangeSet is empty (no changes …","Get the internal map of keychains to their descriptors. …","Return a reference to the internal map of keychain to …","The last active indexes of each keychain","Get the last derivation index revealed for keychain.","Get the last derivation index that is revealed for each …","Returns the highest derivation index of the keychain where …","Returns the highest derivation index of each keychain that …","Store lookahead scripts until target_index.","Convenience method to call lookahead_to_target for …","Return the lookahead setting for each keychain.","Marks the script pubkey at index as used even though it …","Get the next derivation index for keychain. This is the …","Gets the next unused script pubkey in the keychain. I.e. …","Persistence for changes made to a KeychainTracker.","Attempts to reveal the next script pubkey for keychain.","Reveals script pubkeys of the keychain’s descriptor up …","Convenience method to call Self::reveal_to_target on …","Convenience method to get revealed_spks_of_keychain of all …","Iterates over the script pubkeys revealed by this index …","Scans an object for relevant outpoints, which are stored …","Scan a single outpoint for a matching script pubkey.","","","","Set the checkpoint limit of the internal SparseChain.","Set the lookahead count for keychain.","Convenience method to call set_lookahead for all keychains.","Generates script pubkey iterators for every keychain. The …","Generates a script pubkey iterator for the given keychain…","","","","","","","","Get the whole balance visible to the wallet.","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","","","","","","","Index between script pubkeys to transaction outputs","Iterates over all the OutPoint that have a TxOut with a …","","","","","","","Undoes the effect of mark_used. Returns whether the index …","Unconfirmed UTXOs received from an external wallet","Iterates over all unused script pubkeys for a keychain …","The update data in the form of a chain that could be …","","","","","","","The error the backend returns when it fails to load.","Persist wraps a PersistBackend to create a convenient …","A persistence backend for Persist.","The error the backend returns when it fails to write.","Appends a new changeset to the persistance backend.","","","Commit the staged changes to the underlying persistence …","","Returns the argument unchanged.","Calls U::from(self).","Applies all the changesets the backend has received to …","Create a new Persist from a PersistBackend.","Stage a changeset to later persistence with commit.","Get the changes that haven’t been commited yet","","","","","Represents an position in which transactions are ordered …","The return value of determine_changeset.","Occurs when checkpoint of the same height already exists …","Represents a failure when trying to insert a checkpoint …","Represents a failure when trying to insert a Txid into …","The update cannot be applied to the chain because the …","This is a non-monotone structure that tracks relevant Txid…","The update contains inconsistent tx states (e.g. it …","Occurs when the Txid is already in the SparseChain and the …","Occurs when the Txid is to be inserted at a hight higher …","Represents an update failure of SparseChain.","Appends the changes in other into self such that applying …","","Updates SparseChain with another chain that connects to it.","","","","","","","","","","","","Return Txids that would be added to the sparse chain if …","Get the checkpoint at the given height if it exists.","Returns the value set as the checkpoint limit.","Return a BTreeMap of all checkpoints (block hashes by …","","Clears all transactions of height TxHeight::Unconfirmed.","Determines the ChangeSet when all transactions of height …","","","","","","","","","","","","","","Preview changes of updating Self with another chain that …","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Creates a new chain from a list of block hashes and …","Attempt to retrieve a FullTxOut of the given outpoint.","Get the transaction height of the positon.","Derives a ChangeSet that assumes that there are no …","Insert a checkpoint (BlockId).","Determines the resultant ChangeSet if BlockId was inserted.","Inserts a given Txid at pos.","Determines the resultant ChangeSet if Txid was inserted at …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Invalidate checkpoints from_height (inclusive) and above.","Determines the ChangeSet when checkpoints from_height …","Returns whether the sparse chain contains any checkpoints …","Whether this changeset contains no changes.","Get the checkpoint for the last known tip.","Get the positon’s upper bound of a given height.","Get the position’s lower bound of a given height.","","","","Return an iterator over checkpoints in a height range, in …","Iterate over a sub-range of positioned Txids.","Iterate over a sub-range of positioned Txids, where the …","Iterate over a sub-range of positioned Txids, where the …","","Set the checkpoint limit.","Finds the transaction in the chain that spends outpoint.","","","","","","","","","","","","","","","","","","","Return the ChainPosition of a txid.","Iterate over all Txids ordered by their ChainPosition.","","","","","","","Get the unconfirmed position.","","","","","","","","","","","","","","","","","","A structure that represents changes to a TxGraph.","An iterator that traverses transaction descendants.","A graph of transactions and spends.","Iterate over all tx outputs known by TxGraph.","Appends the changes in other into self such that applying …","Applies Additions to TxGraph.","Extends this graph with another so that self becomes the …","","","","","","","","Calculates the fee of a given transaction. Returns 0 if tx …","","","","","","","","","","Previews the resultant Additions when Self is updated …","Given a transaction, return an iterator of txids which …","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Iterate over all full transactions in the graph.","Get a transaction by txid. This only returns Some for full …","Obtains a single tx output (if any) at specified outpoint.","Inserts the given transaction into TxGraph.","Returns the resultant Additions if the given transaction …","Inserts the given TxOut at OutPoint.","Returns the resultant Additions if the given txout is …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Whether the graph has any transactions or outputs in it.","Returns true if the Additions is empty (no transactions or …","Contruct a new TxGraph from a list of transaction.","","The transactions spending from this output.","Iterate over all partial transactions (outputs only) in …","","","","","","","","","","","Iterates over the transactions spending from txid.","","Returns a BTreeMap of vout to output of the provided txid.","Iterates over all outpoints contained within Additions.","","","","","","","Creates an iterator that both filters and maps conflicting …","Creates an iterator that both filters and maps descendants …"],"i":[0,0,0,5,6,0,0,0,0,0,5,6,3,0,3,5,6,7,8,3,5,6,7,8,0,8,3,5,6,7,8,3,5,6,7,8,5,6,7,3,5,7,5,6,7,64,5,6,7,8,3,5,5,6,7,8,65,3,5,5,6,7,7,7,8,5,6,7,5,6,7,3,3,3,5,6,7,8,5,6,8,8,3,8,3,0,3,5,6,5,6,0,3,8,3,5,6,7,3,3,3,5,6,7,0,8,3,3,5,6,7,8,5,3,5,6,7,8,3,5,6,7,8,0,3,8,3,3,3,5,6,7,8,3,3,3,5,6,7,8,66,66,40,35,0,0,39,0,0,39,0,0,40,35,0,41,33,34,34,34,34,34,34,33,39,40,35,41,34,33,39,40,35,41,34,33,34,34,33,39,40,35,41,34,33,39,40,35,41,33,34,33,33,34,34,33,39,40,35,41,34,33,39,39,40,40,35,35,41,41,34,33,34,33,39,40,40,40,35,35,35,41,34,34,34,33,34,34,34,34,34,34,34,34,33,39,40,35,41,34,34,34,33,34,39,40,35,41,33,34,34,34,33,39,40,35,41,39,40,35,41,34,34,33,39,40,35,41,34,33,39,40,35,41,34,34,33,39,40,35,41,41,34,33,39,40,35,41,67,67,0,0,0,0,0,0,0,48,49,52,53,54,52,49,49,53,49,49,49,53,55,49,49,49,52,53,55,54,48,49,52,53,55,54,48,49,49,54,49,49,52,53,55,54,48,49,52,53,55,54,48,48,49,52,53,55,54,48,52,54,53,54,48,49,53,55,48,49,52,53,55,54,48,48,54,49,52,53,55,55,54,54,54,48,49,49,49,48,52,49,49,49,49,49,52,53,55,54,48,53,54,49,52,55,52,52,52,52,52,52,52,52,52,52,0,52,52,52,52,52,52,52,53,54,48,49,52,52,52,52,49,52,53,55,54,48,48,48,48,48,49,52,53,55,54,48,49,52,53,55,54,48,49,52,49,52,53,55,54,48,52,48,52,55,49,52,53,55,54,48,68,0,0,68,68,56,56,56,56,56,56,68,56,56,56,56,56,56,56,0,0,58,0,0,43,0,43,42,42,0,57,37,37,37,37,42,58,43,57,37,42,58,43,57,37,37,37,37,57,37,37,37,42,58,43,57,37,42,58,43,57,37,57,57,37,37,42,58,43,57,37,42,42,58,58,43,43,57,37,42,58,43,57,37,37,21,37,37,37,37,37,37,42,58,43,57,37,37,37,57,37,21,21,42,58,43,37,37,37,37,57,37,37,37,42,58,43,57,42,58,43,37,42,58,43,57,37,42,58,43,57,37,37,57,37,42,58,43,57,21,37,42,58,43,57,69,69,69,70,71,71,71,70,70,72,72,72,0,0,0,36,59,36,36,36,62,36,59,62,36,59,36,62,62,36,59,36,59,36,59,59,36,36,36,59,36,59,36,59,62,36,59,36,36,36,36,36,36,36,62,36,59,62,36,59,36,62,36,36,59,36,59,62,36,59,62,36,59,59,36,59,36,59,62,36,59,62,36,59,36,36],"f":[0,0,0,0,0,0,0,0,0,0,0,0,[[[3,[[0,[1,2]]]]],4],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[[3,[1]]],[[3,[1]]]],[5,5],[6,6],[7,7],[[[8,[1]]],[[8,[1]]]],[[]],[[]],[[]],[[]],[[]],[[5,5],9],[[6,6],9],[[7,7],9],[[],3],[[],5],[[],7],[[],[[10,[5]]]],[[],[[10,[6]]]],[[],[[10,[7]]]],[[],11],[[5,5],12],[[6,6],12],[[7,7],12],[[[8,[13]],8],12],[[[3,[14]],15],16],[[5,15],16],[[5,15],16],[[6,15],16],[[7,15],16],[[[8,[14]],15],16],[17],[[]],[[[19,[18]]],5],[[]],[[]],[[],7],[[],7],[[]],[[]],[5],[6],0,[5,5],[6,5],0,[[[3,[[0,[1,2]]]],20],19],[[[3,[[0,[1,2]]]],[0,[1,2]],20],12],[[]],[[]],[[]],[[]],[[]],[5,12],[6,12],[[[8,[21]],18],12],0,[[[3,[[0,[1,2]]]],22],12],[[[8,[21]],18],12],[[[3,[[0,[1,2]]]]],12],0,[[[3,[[0,[1,2]]]]],12],[5,5],[5,6],[5,5],[5,6],0,[[[3,[[0,[1,2]]]],22],23],0,[[[3,[[0,[1,2]]]],[24,[[0,[1,2]]]]],25],[[5,5],[[19,[9]]]],[[6,6],[[19,[9]]]],[[7,7],[[19,[9]]]],[[[3,[[0,[1,2]]]]],[[26,[[0,[1,2]]]]]],[[[3,[[0,[1,2]]]],27,28],19],[[[3,[[0,[1,2]]]],22]],[5,10],[6,10],[7,10],0,0,[[[3,[[0,[1,2]]]]],[[19,[20]]]],[[]],[[]],[[]],[[]],[[]],[[],29],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],0,[[[3,[[0,[1,2]]]],27],19],0,[[[3,[[0,[1,2]]]]],[[0,[25,30]]]],[[[3,[[0,[1,2]]]],31],25],[[],32],[[],32],[[],32],[[],32],[[],32],[[[3,[[0,[1,2]]]]],12],[[[3,[[0,[1,2]]]]],25],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[33,33]],[[34,33]],[[34,34],[[10,[33,35]]]],[34,34],[34,36],[34,37],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[34,37],0,[34,[[19,[38]]]],[[[34,[1]]],[[34,[1]]]],[[[33,[1]]],[[33,[1]]]],[[[39,[1]]],[[39,[1]]]],[[[40,[1]]],[[40,[1]]]],[[[35,[1]]],[[35,[1]]]],[[[41,[1]]],[[41,[1]]]],[[]],[[]],[[]],[[]],[[]],[[]],[33,12],[[],34],[[],33],[[],[[10,[33]]]],[[34,34],[[10,[33,35]]]],[[[34,[13]],34],12],[[[33,[13]],33],12],[[[39,[13]],39],12],[[[40,[13]],40],12],[[[35,[13]],35],12],[[[41,[13]],41],12],[[[34,[14]],15],16],[[[33,[14]],15],16],[[[39,[14]],15],16],[[[39,[14]],15],16],[[[40,[14]],15],16],[[[40,[14]],15],16],[[[35,[14]],15],16],[[[35,[14]],15],16],[[[41,[14]],15],16],[[[41,[14]],15],16],[[34,17]],[[33,17]],[[]],[[]],[[]],[[]],[41,40],[42,40],[41,35],[43,35],[[]],[[]],[[34,27],[[19,[8]]]],[[34,31],19],[34,36],0,[[34,37,44],[[10,[34,39]]]],[[34,7],[[10,[33,45]]]],[[34,7],[[10,[33,45]]]],[[34,22],[[10,[33,40]]]],[[34,22],[[10,[33,40]]]],[[34,27,28],33],[[34,27,28],33],[[]],[[]],[[]],[[]],[[]],[[]],[[34,18],33],[[34,18],33],[34,12],[33,12],[[37,36],[[10,[34,39]]]],[46],[46],[46],[46],[33,10],[[34,[19,[38]]]],[[34,27],19],[[]],[[]],[[]],[[]],[[]],[[]],[[],29],[[],29],[[],29],[[],29],[34,25],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[34,22],47],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],0,[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,[[48,48],48],[[49,[51,[50]]]],[[[52,[[0,[1,2,14]]]],[0,[1,2,14]],[51,[50]]]],[[[53,[2]],[53,[2]]]],[[54,54]],[[[52,[[0,[1,2,14]]]],[53,[[0,[1,2,14]]]]]],[[49,54]],[[49,55],[[10,[54,35]]]],[53,4],[49,37],[49,34],[49,36],[53,4],[55,36],[[49,17],48],[[49,18],11],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[49,37],[49,34],0,[49,[[19,[38]]]],[[[49,[1,1]]],[[49,[1,1]]]],[[[52,[1]]],[[52,[1]]]],[[[53,[1]]],[[53,[1]]]],[[[55,[1,1]]],[[55,[1,1]]]],[[[54,[1,1]]],[[54,[1,1]]]],[48,48],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],49],[[],52],[[],53],[[],55],[[],54],[[],48],[52],0,[[],[[10,[53]]]],[[],[[10,[54]]]],[[],[[10,[48]]]],[[49,55],[[10,[54,35]]]],[[[53,[13]],53],12],[[[55,[13,13]],55],12],[[48,48],12],[[[49,[14,14]],15],16],[[[52,[14]],15],16],[[[53,[14]],15],16],[[[55,[14,14]],15],16],[[[54,[14,14]],15],16],[[48,15],16],[[48,15],16],[[54,17]],[[]],[[]],[[]],[[]],[34,55],[[]],[53,54],[33,54],[[]],[49,47],[49,47],[49,36],0,[[[52,[[0,[1,2,14]]]]],3],[[49,7],[[10,[54,45]]]],[[49,7],[[10,[54,45]]]],[[49,22],[[10,[54,40]]]],[[49,22],[[10,[54,40]]]],[[]],[[]],[[]],[[]],[[]],[[]],[53,12],[54,12],[49,4],[[[52,[[0,[1,2,14]]]]],4],0,[[[52,[[0,[1,2,14]]]]],[[19,[18]]]],[[[52,[[0,[1,2,14]]]]],4],[[[52,[[0,[1,2,14]]]]],[[19,[18]]]],[[[52,[[0,[1,2,14]]]]],[[4,[[0,[1,2,14]],18]]]],[[[52,[[0,[1,2,14]]]],18]],[[[52,[[0,[1,2,14]]]],[4,[[0,[1,2,14]],18]]]],[[[52,[[0,[1,2,14]]]]],4],[[[52,[[0,[1,2,14]]]],18],12],[[[52,[[0,[1,2,14]]]]]],[[[52,[[0,[1,2,14]]]]]],0,[[[52,[[0,[1,2,14]]]]]],[[[52,[[0,[1,2,14]]]],18]],[[[52,[[0,[1,2,14]]]],4]],[[[52,[[0,[1,2,14]]]]],[[4,[[0,[1,2,14]],[0,[47,1]]]]]],[[[52,[[0,[1,2,14]]]]],[[0,[25,1]]]],[[[52,[[0,[1,2,14]]]]],[[53,[[0,[1,2,14]]]]]],[[[52,[[0,[1,2,14]]]],27,28],[[53,[[0,[1,2,14]]]]]],[53,10],[54,10],[48,10],[[49,[19,[38]]]],[[[52,[[0,[1,2,14]]]],18]],[[[52,[[0,[1,2,14]]]],18]],[[[52,[[0,[1,2,14]]]]],[[4,[[0,[1,2,14]],[0,[47,1]]]]]],[[[52,[[0,[1,2,14]]]]],[[0,[47,1]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[],29],[48,11],0,[48,11],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],0,[[[52,[[0,[1,2,14]]]]],25],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[[52,[[0,[1,2,14]]]],18],12],0,[[[52,[[0,[1,2,14]]]]],25],0,[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,[54,10],[[]],[[]],[56,10],[[[56,[14,14,14]],15],16],[[]],[[]],[49,10],[[],56],[[56,54]],[56,54],[[],10],[[],10],[[],32],[[]],0,0,0,0,0,0,0,0,0,0,0,[[57,57]],[[[37,[21]],[57,[21]]]],[[[37,[21]],[37,[21]]],[[10,[[57,[21]],[43,[21]]]]]],[37,37],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[37,[21]],57],47],[[[37,[21]],18],[[19,[7]]]],[[[37,[21]]],[[19,[38]]]],[[[37,[21]]],4],0,[[[37,[21]]],[[57,[21]]]],[[[37,[21]]],[[57,[21]]]],[[[37,[1]]],[[37,[1]]]],[[[42,[1]]],[[42,[1]]]],[58,58],[[[43,[1]]],[[43,[1]]]],[[[57,[1]]],[[57,[1]]]],[[]],[[]],[[]],[[]],[[]],[[],37],[[],57],[[],[[10,[57]]]],[[[37,[21]],[37,[21]]],[[10,[[57,[21]],[43,[21]]]]]],[[[37,[13]],37],12],[[[42,[13]],42],12],[[58,58],12],[[[43,[13]],43],12],[[[57,[13]],57],12],[[[37,[14]],15],16],[[[42,[14]],15],16],[[[42,[14]],15],16],[[58,15],16],[[58,15],16],[[[43,[14]],15],16],[[[43,[14]],15],16],[[[57,[14]],15],16],[[]],[[]],[[]],[[]],[[]],[[],[[37,[21]]]],[[[37,[21]],36,27],[[19,[[8,[21]]]]]],[[],5],[[[37,[21]]],[[57,[21]]]],[[[37,[21]],7],[[10,[[57,[21]],58]]]],[[[37,[21]],7],[[10,[[57,[21]],58]]]],[[[37,[21]],31,21],[[10,[[57,[21]],[42,[21]]]]]],[[[37,[21]],31,21],[[10,[[57,[21]],[42,[21]]]]]],[[]],[[]],[[]],[[]],[[]],[[[37,[21]],18],[[57,[21]]]],[[[37,[21]],18],[[57,[21]]]],[[[37,[21]]],12],[57,12],[[[37,[21]]],[[19,[7]]]],[5],[5],[46],[46],[46],[[[37,[21]],[24,[18]]],25],[[[37,[21]]],25],[[[37,[21]]],25],[[[37,[21]]],25],[57,10],[[[37,[21]],[19,[38]]]],[[[37,[21]],36,27],19],[[]],[[]],[[]],[[]],[[]],[[],29],[[],29],[[],29],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],[[[37,[21]],31],19],[[[37,[21]]],[[0,[25,30]]]],0,[[],32],[[],32],[[],32],[[],32],[[],32],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[36,47],[[59,59]],[[36,59]],[[36,36],59],[36,36],[[]],[[]],[[]],[[]],[[]],[[]],[[36,22],[[19,[23]]]],[[],[[19,[60]]]],[[],[[19,[61]]]],[36,36],[59,59],[[]],[[]],[[],36],[[],59],[[],[[10,[59]]]],[[36,36],59],[[36,22],47],[[36,36],12],[[59,59],12],[[36,15],16],[[59,15],16],[[36,17]],[[59,17]],[[]],[[]],[[]],[36,47],[[36,31],[[19,[22]]]],[[36,27],[[19,[28]]]],[[36,22],59],[[36,22],59],[[36,27,28],59],[[36,27,28],59],[[]],[[]],[[]],[[]],[36,12],[59,12],[44,36],[62,19],[[36,27],63],[36,47],[59,10],[[]],[[]],[[],10],[[],10],[[],10],[[],10],[[],10],[[],10],0,[[36,31],25],0,[[36,31],[[19,[[4,[18,28]]]]]],[59,47],[[],32],[[],32],[[],32],[[]],[[]],[[]],[[36,22],62],[[36,31],62]],"p":[[8,"Clone"],[8,"Ord"],[3,"SpkTxOutIndex"],[3,"BTreeMap"],[4,"TxHeight"],[4,"ConfirmationTime"],[3,"BlockId"],[3,"FullTxOut"],[4,"Ordering"],[4,"Result"],[15,"u64"],[15,"bool"],[8,"PartialEq"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[8,"FnMut"],[15,"u32"],[4,"Option"],[3,"Script"],[8,"ChainPosition"],[3,"Transaction"],[15,"i64"],[8,"RangeBounds"],[8,"DoubleEndedIterator"],[3,"BTreeSet"],[3,"OutPoint"],[3,"TxOut"],[3,"String"],[8,"ExactSizeIterator"],[3,"Txid"],[3,"TypeId"],[3,"ChangeSet"],[3,"ChainGraph"],[4,"UpdateError"],[3,"TxGraph"],[3,"SparseChain"],[15,"usize"],[4,"NewError"],[4,"InsertTxError"],[3,"UnresolvableConflict"],[4,"InsertTxError"],[4,"UpdateError"],[8,"IntoIterator"],[6,"InsertCheckpointError"],[3,"Demand"],[8,"Iterator"],[3,"Balance"],[3,"KeychainTracker"],[4,"DescriptorPublicKey"],[4,"Descriptor"],[3,"KeychainTxOutIndex"],[3,"DerivationAdditions"],[3,"KeychainChangeSet"],[3,"KeychainScan"],[3,"Persist"],[3,"ChangeSet"],[4,"InsertCheckpointError"],[3,"Additions"],[3,"Amount"],[3,"SignedAmount"],[3,"TxDescendants"],[3,"HashSet"],[8,"DescriptorExt"],[8,"ForEachTxOut"],[13,"Confirmed"],[13,"Conflict"],[8,"PersistBackend"],[13,"HashNotMatching"],[13,"TxMovedUnexpectedly"],[13,"TxTooHigh"],[13,"TxInconsistent"]]},\ +"bdk_coin_select":{"doc":"","t":[3,3,4,4,3,3,13,6,13,3,4,13,13,13,3,4,3,13,13,17,13,13,13,13,13,3,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,12,11,12,11,11,11,11,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,12,12,12,12,11,11,11,11,12,11,12,12,11,12,12,12,11,11,11,11,12,11,11,11,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11],"n":["Bnb","BnbIter","BnbLimit","BranchStrategy","CoinSelector","CoinSelectorOpt","Continue","DecideStrategy","Duration","ExcessStrategy","ExcessStrategyKind","MinAbsoluteFee","MinDrainValue","Rounds","Selection","SelectionConstraint","SelectionError","SkipBoth","SkipInclusion","TXIN_BASE_WEIGHT","TargetFee","TargetValue","ToDrain","ToFee","ToRecipient","WeightedValue","advertise_new_score","all_selected","apply_selection","backtrack","base_weight","best_score","best_strategy","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","candidate","candidates","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","coin_select_bnb","current_excess","current_weight","deselect","drain_value","drain_waste","drain_weight","effective_target","effective_value","eq","eq","excess","excess_strategies","fee","feerate","finish","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","forward","from","from","from","from","from","from","from","from","from","from","from","from","from","from","fund_outputs","hash","input_count","into","into","into","into","into","into","into","into","into","into","into","into","into_iter","into_iter","is_empty","is_segwit","is_selected","long_term_feerate","long_term_feerate","max_extra_target","min_absolute_fee","min_drain_value","new","new","new","next","opts","partial_cmp","pool","pool_pos","provide","recipient_value","rem_abs","rem_eff","select","select_all","select_until_finished","selected","selected","selected_absolute_value","selected_count","selected_effective_value","selected_indexes","selected_waste","selected_weight","selection","spend_drain_weight","target_feerate","target_value","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unselected","unselected_indexes","value","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","waste","weight","weight","will_continue"],"q":["bdk_coin_select","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Bnb represents the current state of the BnB algorithm.","","Determines how we should limit rounds of branch and bound.","Strategy in which we should branch.","CoinSelector is responsible for selecting and deselecting …","","We continue exploring subtrees of this node, starting with …","Closure to decide the branching strategy, alongside a …","","","","Min absolute fee is not met","Min drain value is not met","","","","","We skip both the inclusion and omission branches of this …","We continue exploring ONY the omission branch of this …","Txin “base” fields include outpoint (32+4) and …","The target fee (given the feerate) is not met","The target is not met","","","","A WeightedValue represents an input candidate for …","Compare advertised score with current best. New best will …","","","Attempt to backtrack to the previously selected node’s …","The weight of the template transaction including fixed …","","Returns the ExcessStrategy that results in the least waste.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","This is a variation of the Branch and Bound Coin Selection …","Current excess.","Current weight of template tx + selected inputs.","","","","Additional weight if we include the drain (change) output.","This is the effective target value.","Effective value of this input candidate: …","","","","","","Returns feerate in sats/wu.","","","","","","","","","","","","","Continue down this branch, skip inclusion branch if …","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Total number of inputs; so we can calculate extra varint …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Turns our Bnb state into an iterator.","","","Whether this WeightedValue contains at least one segwit …","","","The feerate","Additional leeway for the target value.","The minimum absolute fee. I.e. needed for RBF.","Minimum value allowed for a drain (change) output.","Creates a new Bnb.","Create a new WeightedValue that represents a single input.","","","","","","","","","","","","","","","","Absolute value sum of all selected inputs.","","Effective value sum of all selected inputs.","","Waste sum of all selected inputs.","Weight sum of all selected inputs.","","Weight of spending the drain (change) output in the future.","The feerate we should try and achieve in sats per weight …","The value we need to select. If the value is None then the …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Total value of the UTXO(s) that this WeightedValue …","","","","","","","","","","","","","","Total weight of including this/these UTXO(s). txin fields: …","",""],"i":[0,0,0,0,0,0,34,0,22,0,0,11,11,22,0,0,0,34,34,0,11,11,12,12,12,0,2,4,5,2,9,2,5,34,2,26,22,8,9,4,10,11,5,12,13,34,2,26,22,8,9,4,10,11,5,12,13,4,4,8,9,4,10,11,5,12,13,8,9,4,10,11,5,12,13,12,0,4,4,4,13,9,9,4,8,11,12,5,5,13,13,4,8,9,4,10,10,11,11,5,12,12,13,2,34,2,26,22,22,22,8,9,4,10,11,5,12,13,9,12,8,34,2,26,22,8,9,4,10,11,5,12,13,2,26,4,8,4,9,9,9,9,9,2,8,4,26,4,12,2,2,10,13,2,2,4,4,4,4,5,4,4,4,4,4,4,2,9,9,9,8,9,4,10,11,5,12,13,10,11,12,34,2,26,22,8,9,4,10,11,5,12,13,34,2,26,22,8,9,4,10,11,5,12,13,34,2,26,22,8,9,4,10,11,5,12,13,4,4,8,34,2,26,22,8,9,4,10,11,5,12,13,13,8,13,34],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[2,[1]],1],3],[4,3],[5,6],[[[2,[1]]],3],0,0,[5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[4,7],8],0,[8,8],[9,9],[4,4],[10,10],[11,11],[5,5],[12,12],[13,13],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[12,12],14],[4,[[15,[4]]]],[4,16],[4,17],[[4,7],3],0,[9,16],0,[4,16],[[8,18],16],[[11,11],3],[[12,12],3],0,0,0,[13,18],[4,[[19,[5,10]]]],[[8,20],21],[[9,20],21],[[4,20],21],[[10,20],21],[[10,20],21],[[11,20],21],[[11,20],21],[[5,20],21],[[12,20],21],[[12,20],21],[[13,20],21],[[[2,[1]],3]],[[]],[[]],[[]],[[]],[7,22],[23,22],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[24,17],9],[12],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[2,[1]],25],[[26,[1]]]],[[]],[4,3],0,[[4,7],3],[9,18],0,0,0,0,[[4,27,1],[[2,[1]]]],[[28,17,3],8],[[27,9],4],[[[26,[[0,[1,29,30]]]]],15],0,[[12,12],[[15,[14]]]],0,0,[31],0,0,0,[[4,7],3],[4],[4,[[19,[5,10]]]],[4,6],0,[4,28],[4,7],[4,16],[4,6],[4,16],[4,17],0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],32],[[],32],[[],32],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[4,6],[4,6],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,[34,3]],"p":[[8,"Ord"],[3,"Bnb"],[15,"bool"],[3,"CoinSelector"],[3,"Selection"],[8,"Iterator"],[15,"usize"],[3,"WeightedValue"],[3,"CoinSelectorOpt"],[3,"SelectionError"],[4,"SelectionConstraint"],[4,"ExcessStrategyKind"],[3,"ExcessStrategy"],[4,"Ordering"],[4,"Option"],[15,"i64"],[15,"u32"],[15,"f32"],[4,"Result"],[3,"Formatter"],[6,"Result"],[4,"BnbLimit"],[3,"Duration"],[3,"TxOut"],[6,"DecideStrategy"],[3,"BnbIter"],[3,"Vec"],[15,"u64"],[8,"Copy"],[8,"Display"],[3,"Demand"],[3,"String"],[3,"TypeId"],[4,"BranchStrategy"]]},\ +"bdk_electrum":{"doc":"This crate is used for updating structures of the bdk_chain…","t":[8,3,11,2,11,11,12,11,2,11,10,11,11,11,12,11,10,11,11,11,11,11],"n":["ElectrumExt","ElectrumUpdate","as_ref","bdk_chain","borrow","borrow_mut","chain_update","default","electrum_client","from","get_tip","into","into_confirmation_time_update","into_keychain_scan","last_active_indices","missing_full_txs","scan","scan_without_keychain","try_from","try_into","type_id","vzip"],"q":["bdk_electrum","","","","","","","","","","","","","","","","","","","","",""],"d":["Trait to extend electrum_client::Client functionality.","The result of ElectrumExt::scan.","","","","","The internal SparseChain update.","","","Returns the argument unchanged.","Fetch the latest block height.","Calls U::from(self).","Creates ElectrumUpdate<K, ConfirmationTime> from …","Transform the ElectrumUpdate into a KeychainScan which can …","The last keychain script pubkey indices which had …","Return a list of missing full transactions that are …","Scan the blockchain (via electrum) for the data specified. …","Convenience method to call scan without requiring a …","","","",""],"i":[0,0,1,0,1,1,1,1,0,1,21,1,1,1,1,1,21,21,1,1,1,1],"f":[0,0,[1,2],0,[[]],[[]],0,[[],1],0,[[]],[[],[[4,[3]]]],[[]],[[[1,[[0,[5,6,7]],8]],9],[[4,[[1,[[0,[5,6,7]],10]],3]]]],[[[1,[[0,[5,6,7]],11]],[13,[12]]],[[4,[[14,[[0,[5,6,7]],11]],[15,[11]]]]]],0,[[[1,[[0,[5,6,7]],11]]],[[13,[16]]]],[[17,[17,[[0,[5,6]],18]],18,18,19,19],[[4,[[1,[[0,[5,6]],8]],3]]]],[[17,18,18,18,19],[[4,[2,3]]]],[[],4],[[],4],[[],20],[[]]],"p":[[3,"ElectrumUpdate"],[3,"SparseChain"],[4,"Error"],[4,"Result"],[8,"Ord"],[8,"Clone"],[8,"Debug"],[4,"TxHeight"],[3,"Client"],[4,"ConfirmationTime"],[8,"ChainPosition"],[3,"Transaction"],[3,"Vec"],[3,"KeychainScan"],[4,"NewError"],[3,"Txid"],[3,"BTreeMap"],[8,"IntoIterator"],[15,"usize"],[3,"TypeId"],[8,"ElectrumExt"]]},\ +"bdk_esplora":{"doc":"BDK Esplora","t":[8,8,2,10,10,11,11,11,11],"n":["EsploraAsyncExt","EsploraExt","esplora_client","scan","scan","scan_without_keychain","scan_without_keychain","scan_without_keychain","scan_without_keychain"],"q":["bdk_esplora","","","","","","","",""],"d":["","Trait to extend esplora_client::BlockingClient …","","Scan the blockchain (via esplora) for the data specified …","Scan the blockchain (via esplora) for the data specified …","Convenience method to call scan without requiring a …","Convenience method to call scan without requiring a …","Convenience method to call scan without requiring a …","Convenience method to call scan without requiring a …"],"i":[0,0,0,15,16,15,15,16,16],"f":[0,0,0,[[1,[1,[[0,[2,3]],4]],4,4,5,5],[[9,[[7,[[0,[2,3]],6]],8]]]],[[1,[1,[[0,[4,10]]]],[0,[4,10]],[0,[4,10]],5,5],[[13,[[12,[11]]]]]],[[1,4,4,4,5],[[9,[[14,[6]],8]]]],[[1,4,4,4,5],[[9,[[14,[6]],8]]]],[[1,[0,[4,10]],[0,[4,10]],[0,[4,10]],5],[[13,[[12,[11]]]]]],[[1,[0,[4,10]],[0,[4,10]],[0,[4,10]],5],[[13,[[12,[11]]]]]]],"p":[[3,"BTreeMap"],[8,"Ord"],[8,"Clone"],[8,"IntoIterator"],[15,"usize"],[4,"ConfirmationTime"],[3,"KeychainScan"],[4,"Error"],[4,"Result"],[8,"Send"],[8,"Future"],[3,"Box"],[3,"Pin"],[3,"ChainGraph"],[8,"EsploraExt"],[8,"EsploraAsyncExt"]]},\ +"bdk_esplora_wallet_example":{"doc":"","t":[17,17,17,5],"n":["PARALLEL_REQUESTS","SEND_AMOUNT","STOP_GAP","main"],"q":["bdk_esplora_wallet_example","","",""],"d":["","","",""],"i":[0,0,0,0],"f":[0,0,0,[[],[[3,[[2,[1]]]]]]],"p":[[8,"Error"],[3,"Box"],[4,"Result"]]},\ +"bdk_file_store":{"doc":"BDK File Store","t":[13,3,4,13,13,13,4,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11],"n":["Bincode","EntryIter","FileError","InvalidMagicBytes","Io","Io","IterError","KeychainStore","aggregate_changeset","append_changeset","append_changeset","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","into","into","into","into","into_iter","iter_changesets","load_into_keychain_tracker","load_into_keychain_tracker","new","new","new_from_path","next","provide","provide","to_string","to_string","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip"],"q":["bdk_file_store","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Failure to decode data from file.","Iterator over entries in a file store.","Error that occurs due to problems encountered with the …","Magic bytes do not match expected.","IO error, this may mean that the file is too short.","Failure to read from file.","Error type for EntryIter.","Persists an append only list of KeychainChangeSet<K,P> to …","Loads all the changesets that have been stored as one …","Append a new changeset to the file and truncate file to …","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Iterates over the stored changeset from first to last …","","Reads and applies all the changesets stored sequentially …","","Creates a new store from a File.","Creates or loads a a store from db_path. If no file exists …","","","","","","","","","","","","","","","","","","","","",""],"i":[9,0,0,8,8,9,0,0,1,1,1,10,1,8,9,10,1,8,9,1,8,8,9,9,10,1,8,8,9,9,10,1,8,9,10,1,1,1,10,1,1,10,8,9,8,9,10,1,8,9,10,1,8,9,10,1,8,9,10,1,8,9],"f":[0,0,0,0,0,0,0,0,[1],[[1,2],[[4,[3]]]],[[1,2],4],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[1,[5,5]],6],7],[[8,6],7],[[8,6],7],[[9,6],7],[[9,6],7],[[]],[[]],[[]],[3,8],[3,9],[[]],[[]],[[]],[[]],[[]],[[]],[1,[[4,[[10,[2]],3]]]],[[1,11],4],[[1,11],[[4,[9]]]],[12,10],[12,[[4,[1,8]]]],[[[14,[13]]],[[4,[1,8]]]],[10,15],[16],[16],[[],17],[[],17],[[],4],[[],4],[[],4],[[],4],[[],4],[[],4],[[],4],[[],4],[[],18],[[],18],[[],18],[[],18],[[]],[[]],[[]],[[]]],"p":[[3,"KeychainStore"],[3,"KeychainChangeSet"],[3,"Error"],[4,"Result"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[4,"FileError"],[4,"IterError"],[3,"EntryIter"],[3,"KeychainTracker"],[3,"File"],[3,"Path"],[8,"AsRef"],[4,"Option"],[3,"Demand"],[3,"String"],[3,"TypeId"]]},\ +"bdk_tmp_plan":{"doc":"A spending plan or plan for short is a representation of a …","t":[3,8,13,13,13,13,3,3,4,4,3,3,13,13,4,13,13,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,11,11,11,11,11,11,11,11,12,12,11,5,11,11,11,11,11,12,12,12,12,12,12,12,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12],"n":["Assets","CanDerive","Complete","DerivationError","Incomplete","Legacy","Plan","PlanKey","PlanState","RequiredSignatures","Requirements","SatisfactionMaterial","Segwitv0","SigHashError","SigningError","TapKey","TapScript","asset_key","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","can_derive","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","default","default","default","default","derivation_hint","descriptor_key","ecdsa_sigs","expected_weight","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","hash160","hash160_images","hash160_preimages","hash256","hash256_images","hash256_preimages","into","into","into","into","into","into","into","into","keys","max_locktime","min_version","plan_satisfaction","provide","required_locktime","required_sequence","requirements","requires_hash_preimages","ripemd160","ripemd160_images","ripemd160_preimages","schnorr_sigs","sha256","sha256_images","sha256_preimages","sign_with_keymap","signatures","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","try_complete","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","txo_age","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","witness_version","final_script_sig","final_script_witness","keys","keys","leaf_hash","merkle_root","plan_key","plan_keys"],"q":["bdk_tmp_plan","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_tmp_plan::PlanState","","bdk_tmp_plan::RequiredSignatures","","","","",""],"d":["","","The plan is complete","","","Legacy ECDSA signatures are required","A plan represents a particular spending path for a …","A plan key contains the asset key originally provided …","The returned value from Plan::try_complete.","The signatures required to complete the plan","Signatures and hash pre-images that must be provided to …","Signatures and hash pre-images that can be used to …","Segwitv0 ECDSA signatures are required","","","A Taproot key spend signature is required","Taproot script path signatures are required","The key the planner will sign with","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","A hint from how to get from the asset key to the concrete …","The key that was in the descriptor that we are satisfying …","ECDSA signatures under their keys","The expected satisfaction weight for the plan if it is …","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","required hash160 pre-images","hash160 pre-images under their images","","required hash256 pre-images","hash256 pre-images under their images","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","The minmum required transaction version required on the …","","","The minimum required locktime height or time on the …","The minimum required sequence (height or time) on the …","","Whether any hash pre-images are required in the plan","","required ripemd160 pre-images","ripemd160 pre-images under their images","Schnorr signautres under their keys","","required sha256 pre-images","SHA256 pre-images under their images","","required signatures","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Witness version for the plan","The script sig that should be set on the input","The witness that should be set on the input","","","The leaf hash of the script being used","The merkle root of the taproot output","the internal key","The keys in the script that require signatures"],"i":[0,0,33,7,33,6,0,0,0,0,0,0,6,7,0,6,6,8,33,5,6,7,8,9,10,11,33,5,6,7,8,9,10,11,36,5,6,7,8,9,10,11,5,6,7,8,9,10,11,5,6,10,11,8,8,10,9,5,6,7,7,8,9,10,11,33,5,6,7,7,7,8,9,10,11,11,5,10,11,5,10,33,5,6,7,8,9,10,11,11,11,9,0,7,9,9,9,5,11,5,10,10,11,5,10,6,5,5,6,7,8,9,10,11,7,9,33,5,6,7,8,9,10,11,33,5,6,7,8,9,10,11,11,33,5,6,7,8,9,10,11,33,5,6,7,8,9,10,11,9,37,37,38,39,40,41,41,40],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[1,[[3,[2]]]],[[[5,[4]]],[[5,[4]]]],[[[6,[4]]],[[6,[4]]]],[7,7],[[[8,[4]]],[[8,[4]]]],[[[9,[4]]],[[9,[4]]]],[10,10],[[[11,[4]]],[[11,[4]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],5],[[],6],[[],10],[[],11],0,0,0,[9,12],[[[5,[13]],14],15],[[[6,[13]],14],15],[[7,14],15],[[7,14],15],[[[8,[13]],14],15],[[[9,[13]],14],15],[[10,14],15],[[[11,[13]],14],15],[[]],[[]],[[]],[16,7],[[]],[17,7],[[]],[[]],[[]],[[]],0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[9,[[3,[18]]]],[[19,11],[[3,[9]]]],[20],[9,[[3,[21]]]],[9,[[3,[22]]]],[9,5],[5,23],0,0,0,0,0,0,0,[[[6,[24]],12,25,26,[3,[27]],[3,[28]],29,10,30],[[31,[23,7]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],32],[[9,10],33],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],[[],31],0,[[],34],[[],34],[[],34],[[],34],[[],34],[[],34],[[],34],[[],34],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[9,[[3,[35]]]],0,0,0,0,0,0,0,0],"p":[[3,"DefiniteDescriptorKey"],[3,"DerivationPath"],[4,"Option"],[8,"Clone"],[3,"Requirements"],[4,"RequiredSignatures"],[4,"SigningError"],[3,"PlanKey"],[3,"Plan"],[3,"SatisfactionMaterial"],[3,"Assets"],[15,"usize"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[4,"Error"],[4,"Error"],[15,"u32"],[4,"Descriptor"],[3,"Demand"],[4,"LockTime"],[3,"Sequence"],[15,"bool"],[4,"DescriptorPublicKey"],[6,"KeyMap"],[4,"Prevouts"],[4,"SchnorrSighashType"],[4,"EcdsaSighashType"],[3,"SighashCache"],[3,"Secp256k1"],[4,"Result"],[3,"String"],[4,"PlanState"],[3,"TypeId"],[4,"WitnessVersion"],[8,"CanDerive"],[13,"Complete"],[13,"Legacy"],[13,"Segwitv0"],[13,"TapScript"],[13,"TapKey"]]},\ +"keychain_tracker_electrum_example":{"doc":"","t":[4,13,3,13,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12],"n":["ElectrumCommands","Scan","ScanOptions","Sync","augment_args","augment_args_for_update","augment_subcommands","augment_subcommands_for_update","batch_size","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","eq","fmt","fmt","from","from","from_arg_matches","from_arg_matches","from_arg_matches_mut","from_arg_matches_mut","has_subcommand","into","into","into_app","into_app_for_update","main","to_owned","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","update_from_arg_matches","update_from_arg_matches","update_from_arg_matches_mut","update_from_arg_matches_mut","vzip","vzip","all_spks","scan_options","scan_options","stop_gap","unconfirmed","unused_spks","utxos"],"q":["keychain_tracker_electrum_example","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","keychain_tracker_electrum_example::ElectrumCommands","","","","","",""],"d":["","Scans the addresses in the wallet using esplora API.","","Scans particular addresses using esplora API","","","","","Set batch size for each script_history call to electrum …","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","Scan every address that you have derived","","","When a gap this large has been found for a keychain it …","Scan unconfirmed transactions for updates","Scan all the unused addresses","Scan unspent outpoints for spends or changes to …"],"i":[0,2,0,2,3,3,2,2,3,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,2,3,3,3,0,2,3,2,3,2,3,2,3,2,3,2,3,2,3,13,14,13,14,13,13,13],"f":[0,0,0,0,[1,1],[1,1],[1,1],[1,1],0,[[]],[[]],[[]],[[]],[2,2],[3,3],[[]],[[]],[[3,3],4],[[2,5],6],[[3,5],6],[[]],[[]],[7,[[9,[2,8]]]],[7,[[9,[3,8]]]],[7,[[9,[2,8]]]],[7,[[9,[3,8]]]],[10,4],[[]],[[]],[[],1],[[],1],[[],11],[[]],[[]],[[],9],[[],9],[[],9],[[],9],[[],12],[[],12],[[2,7],[[9,[8]]]],[[3,7],[[9,[8]]]],[[2,7],[[9,[8]]]],[[3,7],[[9,[8]]]],[[]],[[]],0,0,0,0,0,0,0],"p":[[6,"Command"],[4,"ElectrumCommands"],[3,"ScanOptions"],[15,"bool"],[3,"Formatter"],[6,"Result"],[3,"ArgMatches"],[3,"Error"],[4,"Result"],[15,"str"],[6,"Result"],[3,"TypeId"],[13,"Sync"],[13,"Scan"]]},\ +"keychain_tracker_esplora_example":{"doc":"","t":[4,13,3,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12],"n":["EsploraCommands","Scan","ScanOptions","Sync","augment_args","augment_args_for_update","augment_subcommands","augment_subcommands_for_update","borrow","borrow","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","eq","fmt","fmt","from","from","from_arg_matches","from_arg_matches","from_arg_matches_mut","from_arg_matches_mut","has_subcommand","into","into","into_app","into_app_for_update","main","parallel_requests","to_owned","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","update_from_arg_matches","update_from_arg_matches","update_from_arg_matches_mut","update_from_arg_matches_mut","vzip","vzip","all_spks","scan_options","scan_options","stop_gap","unconfirmed","unused_spks","utxos"],"q":["keychain_tracker_esplora_example","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","keychain_tracker_esplora_example::EsploraCommands","","","","","",""],"d":["","Scans the addresses in the wallet using esplora API.","","Scans particular addresses using esplora API","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","Scan every address that you have derived","","","When a gap this large has been found for a keychain it …","Scan unconfirmed transactions for updates","Scan all the unused addresses","Scan unspent outpoints for spends or changes to …"],"i":[0,2,0,2,3,3,2,2,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,2,3,3,3,0,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,13,14,13,14,13,13,13],"f":[0,0,0,0,[1,1],[1,1],[1,1],[1,1],[[]],[[]],[[]],[[]],[2,2],[3,3],[[]],[[]],[[3,3],4],[[2,5],6],[[3,5],6],[[]],[[]],[7,[[9,[2,8]]]],[7,[[9,[3,8]]]],[7,[[9,[2,8]]]],[7,[[9,[3,8]]]],[10,4],[[]],[[]],[[],1],[[],1],[[],11],0,[[]],[[]],[[],9],[[],9],[[],9],[[],9],[[],12],[[],12],[[2,7],[[9,[8]]]],[[3,7],[[9,[8]]]],[[2,7],[[9,[8]]]],[[3,7],[[9,[8]]]],[[]],[[]],0,0,0,0,0,0,0],"p":[[6,"Command"],[4,"EsploraCommands"],[3,"ScanOptions"],[15,"bool"],[3,"Formatter"],[6,"Result"],[3,"ArgMatches"],[3,"Error"],[4,"Result"],[15,"str"],[6,"Result"],[3,"TypeId"],[13,"Sync"],[13,"Scan"]]},\ +"keychain_tracker_example_cli":{"doc":"","t":[13,4,3,3,13,13,13,4,4,13,13,13,4,13,13,13,13,13,13,13,13,13,13,4,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,2,11,11,11,11,11,11,11,11,11,11,11,12,12,5,12,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,5,11,11,11,11,11,11,11,11,11,12,11,5,5,5,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12],"n":["Address","AddressCmd","AddrsOutput","Args","Balance","BranchAndBound","ChainSpecific","CoinSelectionAlgo","Commands","External","Index","Internal","Keychain","LargestFirst","List","List","New","NewestFirst","Next","OldestFirst","Send","SmallestFirst","TxOut","TxOutCmd","augment_args","augment_args_for_update","augment_subcommands","augment_subcommands","augment_subcommands","augment_subcommands_for_update","augment_subcommands_for_update","augment_subcommands_for_update","bdk_file_store","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_descriptor","clap","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","command","cp_limit","create_tx","db_path","default","descriptor","deserialize","deserialize","eq","equivalent","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from_arg_matches","from_arg_matches","from_arg_matches","from_arg_matches","from_arg_matches_mut","from_arg_matches_mut","from_arg_matches_mut","from_arg_matches_mut","from_str","handle_commands","has_subcommand","has_subcommand","has_subcommand","init","into","into","into","into","into","into","into","into_app","into_app_for_update","network","partial_cmp","planned_utxos","run_address_cmd","run_balance_cmd","run_txo_cmd","serialize","serialize","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","update_from_arg_matches","update_from_arg_matches","update_from_arg_matches","update_from_arg_matches","update_from_arg_matches_mut","update_from_arg_matches_mut","update_from_arg_matches_mut","update_from_arg_matches_mut","vzip","vzip","vzip","vzip","vzip","vzip","vzip","change","addr_cmd","address","coin_select","txout_cmd","value","confirmed","spent","unconfirmed","unspent"],"q":["keychain_tracker_example_cli","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","keychain_tracker_example_cli::AddressCmd","keychain_tracker_example_cli::Commands","","","","","keychain_tracker_example_cli::TxOutCmd","","",""],"d":["Address generation and inspection","","A structure defining output of a AddressCmd execution.","","Get the wallet balance","","","","","","","","","","List all addresses","","Get a new address regardless if the existing ones haven’…","","Get the next unused address","","Send coins to an address","","TxOut related commands","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","","","","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return only confirmed outputs","Return only spent outputs","Return only unconfirmed outputs","Return only unspent outputs"],"i":[4,0,0,0,4,5,4,0,0,8,6,8,0,5,6,7,6,5,6,5,4,5,4,0,22,22,4,6,7,4,6,7,0,22,4,5,6,7,8,16,22,4,5,6,7,8,16,22,0,4,5,6,7,8,4,5,6,7,8,8,22,22,0,22,5,22,8,16,8,8,4,5,5,6,7,8,8,22,4,5,6,7,8,16,22,4,6,7,22,4,6,7,5,0,4,6,7,0,22,4,5,6,7,8,16,22,22,22,8,0,0,0,0,8,16,4,5,6,7,8,5,8,22,4,5,6,7,8,16,22,4,5,6,7,8,16,22,4,5,6,7,8,16,22,4,6,7,22,4,6,7,22,4,5,6,7,8,16,33,34,35,35,36,35,37,37,37,37],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[1,1],[1,1],[1,1],[1,1],[1,1],[1,1],[1,1],[1,1],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[[4,[[0,[2,3]]]]],[[4,[[0,[2,3]]]]]],[5,5],[6,6],[7,7],[8,8],[[]],[[]],[[]],[[]],[[]],[[8,8],9],0,0,[[10,11,5,12,13],14],0,[[],5],0,[[],[[15,[8]]]],[[],[[15,[16]]]],[[8,8],17],[[],17],[[[4,[[0,[18,3]]]],19],20],[[5,19],20],[[5,19],20],[[6,19],20],[[7,19],20],[[8,19],20],[[8,19],20],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[21,[[15,[[22,[3]],23]]]],[21,[[15,[[4,[3]],23]]]],[21,[[15,[6,23]]]],[21,[[15,[7,23]]]],[21,[[15,[[22,[3]],23]]]],[21,[[15,[[4,[3]],23]]]],[21,[[15,[6,23]]]],[21,[[15,[7,23]]]],[24,[[14,[5]]]],[[[4,[3]],25,26,26,27,13],14],[24,17],[24,17],[24,17],[[],14],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],1],[[],1],0,[[8,8],[[28,[9]]]],[[12,29],30],[[26,26,6,27],14],[26],[[7,26,27]],[8,15],[16,15],[[]],[[]],[[]],[[]],[[]],[[],31],[[],31],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[],32],[[[22,[3]],21],[[15,[23]]]],[[[4,[3]],21],[[15,[23]]]],[[6,21],[[15,[23]]]],[[7,21],[[15,[23]]]],[[[22,[3]],21],[[15,[23]]]],[[[4,[3]],21],[[15,[23]]]],[[6,21],[[15,[23]]]],[[7,21],[[15,[23]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0],"p":[[6,"Command"],[8,"Clone"],[8,"Subcommand"],[4,"Commands"],[4,"CoinSelectionAlgo"],[4,"AddressCmd"],[4,"TxOutCmd"],[4,"Keychain"],[4,"Ordering"],[15,"u64"],[3,"Address"],[3,"KeychainTracker"],[3,"HashMap"],[6,"Result"],[4,"Result"],[3,"AddrsOutput"],[15,"bool"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[3,"ArgMatches"],[3,"Args"],[3,"Error"],[15,"str"],[8,"FnOnce"],[3,"Mutex"],[4,"Network"],[4,"Option"],[3,"Assets"],[8,"Iterator"],[3,"String"],[3,"TypeId"],[13,"List"],[13,"Address"],[13,"Send"],[13,"TxOut"],[13,"List"]]},\ +"wallet_electrum_example":{"doc":"","t":[17,17,17,5],"n":["BATCH_SIZE","SEND_AMOUNT","STOP_GAP","main"],"q":["wallet_electrum_example","","",""],"d":["","","",""],"i":[0,0,0,0],"f":[0,0,0,[[],[[3,[[2,[1]]]]]]],"p":[[8,"Error"],[3,"Box"],[4,"Result"]]},\ +"wallet_esplora_async":{"doc":"","t":[17,17,17,5],"n":["PARALLEL_REQUESTS","SEND_AMOUNT","STOP_GAP","main"],"q":["wallet_esplora_async","","",""],"d":["","","",""],"i":[0,0,0,0],"f":[0,0,0,[[],[[3,[[2,[1]]]]]]],"p":[[8,"Error"],[3,"Box"],[4,"Result"]]}\ }'); if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)}; if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html index 9cff0c494d..84a9af5c58 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html @@ -1,2 +1 @@ -Rustdoc settings

    Rustdoc settings

    Back
    \ No newline at end of file +Rustdoc settings

    Rustdoc settings

    Back
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-files.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-files.js index 8777308688..928ce88cc1 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-files.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-files.js @@ -1,4 +1,16 @@ var sourcesIndex = JSON.parse('{\ -"bdk":["",[["blockchain",[["compact_filters",[],["mod.rs","peer.rs","store.rs","sync.rs"]],["esplora",[],["blocking.rs","mod.rs"]]],["any.rs","electrum.rs","mod.rs","rpc.rs","script_sync.rs"]],["database",[],["any.rs","keyvalue.rs","memory.rs","mod.rs","sqlite.rs"]],["descriptor",[],["checksum.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]],["keys",[],["bip39.rs","mod.rs"]],["psbt",[],["mod.rs"]],["testutils",[],["mod.rs"]],["wallet",[],["coin_selection.rs","export.rs","hardwaresigner.rs","mod.rs","signer.rs","time.rs","tx_builder.rs","utils.rs","verify.rs"]]],["error.rs","lib.rs","types.rs"]]\ +"bdk":["",[["descriptor",[],["checksum.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]],["keys",[],["mod.rs"]],["psbt",[],["mod.rs"]],["wallet",[],["coin_selection.rs","export.rs","mod.rs","signer.rs","tx_builder.rs","utils.rs"]]],["error.rs","lib.rs","types.rs"]],\ +"bdk_chain":["",[["keychain",[],["persist.rs","tracker.rs","txout_index.rs"]]],["chain_data.rs","chain_graph.rs","descriptor_ext.rs","example_utils.rs","keychain.rs","lib.rs","sparse_chain.rs","spk_txout_index.rs","tx_data_traits.rs","tx_graph.rs"]],\ +"bdk_coin_select":["",[],["bnb.rs","coin_selector.rs","lib.rs"]],\ +"bdk_electrum":["",[],["lib.rs"]],\ +"bdk_esplora":["",[],["async_ext.rs","blocking_ext.rs","lib.rs"]],\ +"bdk_esplora_wallet_example":["",[],["main.rs"]],\ +"bdk_file_store":["",[],["file_store.rs","lib.rs"]],\ +"bdk_tmp_plan":["",[],["lib.rs","plan_impls.rs","requirements.rs","template.rs"]],\ +"keychain_tracker_electrum_example":["",[],["main.rs"]],\ +"keychain_tracker_esplora_example":["",[],["main.rs"]],\ +"keychain_tracker_example_cli":["",[],["lib.rs"]],\ +"wallet_electrum_example":["",[],["main.rs"]],\ +"wallet_esplora_async":["",[],["main.rs"]]\ }'); createSourceSidebar(); diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html deleted file mode 100644 index 134542eb89..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html +++ /dev/null @@ -1,499 +0,0 @@ -any.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Runtime-checked blockchain types
    -//!
    -//! This module provides the implementation of [`AnyBlockchain`] which allows switching the
    -//! inner [`Blockchain`] type at runtime.
    -//!
    -//! ## Example
    -//!
    -//! When paired with the use of [`ConfigurableBlockchain`], it allows creating any
    -//! blockchain type supported using a single line of code:
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::blockchain::*;
    -//! # #[cfg(all(feature = "esplora", feature = "ureq"))]
    -//! # {
    -//! let config = serde_json::from_str("...")?;
    -//! let blockchain = AnyBlockchain::from_config(&config)?;
    -//! let height = blockchain.get_height();
    -//! # }
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use super::*;
    -
    -macro_rules! impl_from {
    -    ( boxed $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
    -        $( $cfg )*
    -        impl From<$from> for $to {
    -            fn from(inner: $from) -> Self {
    -                <$to>::$variant(Box::new(inner))
    -            }
    -        }
    -    };
    -    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
    -        $( $cfg )*
    -        impl From<$from> for $to {
    -            fn from(inner: $from) -> Self {
    -                <$to>::$variant(inner)
    -            }
    -        }
    -    };
    -}
    -
    -macro_rules! impl_inner_method {
    -    ( $self:expr, $name:ident $(, $args:expr)* ) => {
    -        match $self {
    -            #[cfg(feature = "electrum")]
    -            AnyBlockchain::Electrum(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "esplora")]
    -            AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "compact_filters")]
    -            AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "rpc")]
    -            AnyBlockchain::Rpc(inner) => inner.$name( $($args, )* ),
    -        }
    -    }
    -}
    -
    -/// Type that can contain any of the [`Blockchain`] types defined by the library
    -///
    -/// It allows switching backend at runtime
    -///
    -/// See [this module](crate::blockchain::any)'s documentation for a usage example.
    -pub enum AnyBlockchain {
    -    #[cfg(feature = "electrum")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -    /// Electrum client
    -    Electrum(Box<electrum::ElectrumBlockchain>),
    -    #[cfg(feature = "esplora")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -    /// Esplora client
    -    Esplora(Box<esplora::EsploraBlockchain>),
    -    #[cfg(feature = "compact_filters")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -    /// Compact filters client
    -    CompactFilters(Box<compact_filters::CompactFiltersBlockchain>),
    -    #[cfg(feature = "rpc")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
    -    /// RPC client
    -    Rpc(Box<rpc::RpcBlockchain>),
    -}
    -
    -#[maybe_async]
    -impl Blockchain for AnyBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        maybe_await!(impl_inner_method!(self, get_capabilities))
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(self, broadcast, tx))
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        maybe_await!(impl_inner_method!(self, estimate_fee, target))
    -    }
    -}
    -
    -#[maybe_async]
    -impl GetHeight for AnyBlockchain {
    -    fn get_height(&self) -> Result<u32, Error> {
    -        maybe_await!(impl_inner_method!(self, get_height))
    -    }
    -}
    -
    -#[maybe_async]
    -impl GetTx for AnyBlockchain {
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        maybe_await!(impl_inner_method!(self, get_tx, txid))
    -    }
    -}
    -
    -#[maybe_async]
    -impl GetBlockHash for AnyBlockchain {
    -    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error> {
    -        maybe_await!(impl_inner_method!(self, get_block_hash, height))
    -    }
    -}
    -
    -#[maybe_async]
    -impl WalletSync for AnyBlockchain {
    -    fn wallet_sync<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(
    -            self,
    -            wallet_sync,
    -            database,
    -            progress_update
    -        ))
    -    }
    -
    -    fn wallet_setup<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(
    -            self,
    -            wallet_setup,
    -            database,
    -            progress_update
    -        ))
    -    }
    -}
    -
    -impl_from!(boxed electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
    -impl_from!(boxed esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
    -impl_from!(boxed compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
    -impl_from!(boxed rpc::RpcBlockchain, AnyBlockchain, Rpc, #[cfg(feature = "rpc")]);
    -
    -/// Type that can contain any of the blockchain configurations defined by the library
    -///
    -/// This allows storing a single configuration that can be loaded into an [`AnyBlockchain`]
    -/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
    -/// will find this particularly useful.
    -///
    -/// This type can be serialized from a JSON object like:
    -///
    -/// ```
    -/// # #[cfg(feature = "electrum")]
    -/// # {
    -/// use bdk::blockchain::{electrum::ElectrumBlockchainConfig, AnyBlockchainConfig};
    -/// let config: AnyBlockchainConfig = serde_json::from_str(
    -///     r#"{
    -///    "type" : "electrum",
    -///    "url" : "ssl://electrum.blockstream.info:50002",
    -///    "retry": 2,
    -///    "stop_gap": 20,
    -///    "validate_domain": true
    -/// }"#,
    -/// )
    -/// .unwrap();
    -/// assert_eq!(
    -///     config,
    -///     AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig {
    -///         url: "ssl://electrum.blockstream.info:50002".into(),
    -///         retry: 2,
    -///         socks5: None,
    -///         timeout: None,
    -///         stop_gap: 20,
    -///         validate_domain: true,
    -///     })
    -/// );
    -/// # }
    -/// ```
    -#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Eq)]
    -#[serde(tag = "type", rename_all = "snake_case")]
    -pub enum AnyBlockchainConfig {
    -    #[cfg(feature = "electrum")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -    /// Electrum client
    -    Electrum(electrum::ElectrumBlockchainConfig),
    -    #[cfg(feature = "esplora")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -    /// Esplora client
    -    Esplora(esplora::EsploraBlockchainConfig),
    -    #[cfg(feature = "compact_filters")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -    /// Compact filters client
    -    CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
    -    #[cfg(feature = "rpc")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
    -    /// RPC client configuration
    -    Rpc(rpc::RpcConfig),
    -}
    -
    -impl ConfigurableBlockchain for AnyBlockchain {
    -    type Config = AnyBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(match config {
    -            #[cfg(feature = "electrum")]
    -            AnyBlockchainConfig::Electrum(inner) => {
    -                AnyBlockchain::Electrum(Box::new(electrum::ElectrumBlockchain::from_config(inner)?))
    -            }
    -            #[cfg(feature = "esplora")]
    -            AnyBlockchainConfig::Esplora(inner) => {
    -                AnyBlockchain::Esplora(Box::new(esplora::EsploraBlockchain::from_config(inner)?))
    -            }
    -            #[cfg(feature = "compact_filters")]
    -            AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(Box::new(
    -                compact_filters::CompactFiltersBlockchain::from_config(inner)?,
    -            )),
    -            #[cfg(feature = "rpc")]
    -            AnyBlockchainConfig::Rpc(inner) => {
    -                AnyBlockchain::Rpc(Box::new(rpc::RpcBlockchain::from_config(inner)?))
    -            }
    -        })
    -    }
    -}
    -
    -impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
    -impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
    -impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
    -impl_from!(rpc::RpcConfig, AnyBlockchainConfig, Rpc, #[cfg(feature = "rpc")]);
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html deleted file mode 100644 index 95bdbd1e35..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html +++ /dev/null @@ -1,1239 +0,0 @@ -mod.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Compact Filters
    -//!
    -//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
    -//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
    -//! by downloading compact filters from the P2P network.
    -//!
    -//! Since there are currently very few peers "in the wild" that advertise the required service
    -//! flag, this implementation requires that one or more known peers are provided by the user.
    -//! No dns or other kinds of peer discovery are done internally.
    -//!
    -//! Moreover, this module doesn't currently support detecting and resolving conflicts between
    -//! messages received by different peers. Thus, it's recommended to use this module by only
    -//! connecting to a single peer at a time, optionally by opening multiple connections if it's
    -//! desirable to use multiple threads at once to sync in parallel.
    -//!
    -//! This is an **EXPERIMENTAL** feature, API and other major changes are expected.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use std::sync::Arc;
    -//! # use bitcoin::*;
    -//! # use bdk::*;
    -//! # use bdk::blockchain::compact_filters::*;
    -//! let num_threads = 4;
    -//!
    -//! let mempool = Arc::new(Mempool::default());
    -//! let peers = (0..num_threads)
    -//!     .map(|_| {
    -//!         Peer::connect(
    -//!             "btcd-mainnet.lightning.computer:8333",
    -//!             Arc::clone(&mempool),
    -//!             Network::Bitcoin,
    -//!         )
    -//!     })
    -//!     .collect::<Result<_, _>>()?;
    -//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
    -//! # Ok::<(), CompactFiltersError>(())
    -//! ```
    -
    -use std::collections::HashSet;
    -use std::fmt;
    -use std::ops::DerefMut;
    -use std::path::Path;
    -use std::sync::atomic::{AtomicUsize, Ordering};
    -use std::sync::{Arc, Mutex};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::network::message_blockdata::Inventory;
    -use bitcoin::{Network, OutPoint, Transaction, Txid};
    -
    -use rocksdb::{Options, SliceTransform, DB};
    -
    -mod peer;
    -mod store;
    -mod sync;
    -
    -use crate::blockchain::*;
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::error::Error;
    -use crate::types::{KeychainKind, LocalUtxo, TransactionDetails};
    -use crate::{BlockTime, FeeRate};
    -
    -use peer::*;
    -use store::*;
    -use sync::*;
    -
    -pub use peer::{Mempool, Peer};
    -
    -const SYNC_HEADERS_COST: f32 = 1.0;
    -const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
    -const PROCESS_BLOCKS_COST: f32 = 20_000.0;
    -
    -/// Structure implementing the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
    -#[derive(Debug)]
    -pub struct CompactFiltersBlockchain {
    -    peers: Vec<Arc<Peer>>,
    -    headers: Arc<ChainStore<Full>>,
    -    skip_blocks: Option<usize>,
    -}
    -
    -impl CompactFiltersBlockchain {
    -    /// Construct a new instance given a list of peers, a path to store headers and block
    -    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
    -    /// from the genesis while scanning for the wallet's outputs.
    -    ///
    -    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
    -    /// in parallel. It's currently recommended to only connect to a single peer to avoid
    -    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
    -    /// speed-up the sync process.
    -    pub fn new<P: AsRef<Path>>(
    -        peers: Vec<Peer>,
    -        storage_dir: P,
    -        skip_blocks: Option<usize>,
    -    ) -> Result<Self, CompactFiltersError> {
    -        if peers.is_empty() {
    -            return Err(CompactFiltersError::NoPeers);
    -        }
    -
    -        let mut opts = Options::default();
    -        opts.create_if_missing(true);
    -        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
    -
    -        let network = peers[0].get_network();
    -
    -        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or_else(|_| vec!["default".to_string()]);
    -        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
    -        let headers = Arc::new(ChainStore::new(db, network)?);
    -
    -        // try to recover partial snapshots
    -        for cf_name in &cfs {
    -            if !cf_name.starts_with("_headers:") {
    -                continue;
    -            }
    -
    -            info!("Trying to recover: {:?}", cf_name);
    -            headers.recover_snapshot(cf_name)?;
    -        }
    -
    -        Ok(CompactFiltersBlockchain {
    -            peers: peers.into_iter().map(Arc::new).collect(),
    -            headers,
    -            skip_blocks,
    -        })
    -    }
    -
    -    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
    -    /// outputs that send funds to a know script_pubkey.
    -    fn process_tx<D: BatchDatabase>(
    -        &self,
    -        database: &mut D,
    -        tx: &Transaction,
    -        height: Option<u32>,
    -        timestamp: Option<u64>,
    -        internal_max_deriv: &mut Option<u32>,
    -        external_max_deriv: &mut Option<u32>,
    -    ) -> Result<(), Error> {
    -        let mut updates = database.begin_batch();
    -
    -        let mut incoming: u64 = 0;
    -        let mut outgoing: u64 = 0;
    -
    -        let mut inputs_sum: u64 = 0;
    -        let mut outputs_sum: u64 = 0;
    -
    -        // look for our own inputs
    -        for (i, input) in tx.input.iter().enumerate() {
    -            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
    -                inputs_sum += previous_output.value;
    -
    -                // this output is ours, we have a path to derive it
    -                if let Some((keychain, _)) =
    -                    database.get_path_from_script_pubkey(&previous_output.script_pubkey)?
    -                {
    -                    outgoing += previous_output.value;
    -
    -                    debug!("{} input #{} is mine, setting utxo as spent", tx.txid(), i);
    -                    updates.set_utxo(&LocalUtxo {
    -                        outpoint: input.previous_output,
    -                        txout: previous_output.clone(),
    -                        keychain,
    -                        is_spent: true,
    -                    })?;
    -                }
    -            }
    -        }
    -
    -        for (i, output) in tx.output.iter().enumerate() {
    -            // to compute the fees later
    -            outputs_sum += output.value;
    -
    -            // this output is ours, we have a path to derive it
    -            if let Some((keychain, child)) =
    -                database.get_path_from_script_pubkey(&output.script_pubkey)?
    -            {
    -                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
    -                updates.set_utxo(&LocalUtxo {
    -                    outpoint: OutPoint::new(tx.txid(), i as u32),
    -                    txout: output.clone(),
    -                    keychain,
    -                    is_spent: false,
    -                })?;
    -                incoming += output.value;
    -
    -                if keychain == KeychainKind::Internal
    -                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
    -                {
    -                    *internal_max_deriv = Some(child);
    -                } else if keychain == KeychainKind::External
    -                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
    -                {
    -                    *external_max_deriv = Some(child);
    -                }
    -            }
    -        }
    -
    -        if incoming > 0 || outgoing > 0 {
    -            let tx = TransactionDetails {
    -                txid: tx.txid(),
    -                transaction: Some(tx.clone()),
    -                received: incoming,
    -                sent: outgoing,
    -                confirmation_time: BlockTime::new(height, timestamp),
    -                fee: Some(inputs_sum.saturating_sub(outputs_sum)),
    -            };
    -
    -            info!("Saving tx {}", tx.txid);
    -            updates.set_tx(&tx)?;
    -        }
    -
    -        database.commit_batch(updates)?;
    -
    -        Ok(())
    -    }
    -}
    -
    -impl Blockchain for CompactFiltersBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![Capability::FullHistory].into_iter().collect()
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        self.peers[0].broadcast_tx(tx.clone())?;
    -
    -        Ok(())
    -    }
    -
    -    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
    -        // TODO
    -        Ok(FeeRate::default())
    -    }
    -}
    -
    -impl GetHeight for CompactFiltersBlockchain {
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(self.headers.get_height()? as u32)
    -    }
    -}
    -
    -impl GetTx for CompactFiltersBlockchain {
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.peers[0]
    -            .get_mempool()
    -            .get_tx(&Inventory::Transaction(*txid)))
    -    }
    -}
    -
    -impl GetBlockHash for CompactFiltersBlockchain {
    -    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error> {
    -        self.headers
    -            .get_block_hash(height as usize)?
    -            .ok_or(Error::CompactFilters(
    -                CompactFiltersError::BlockHashNotFound,
    -            ))
    -    }
    -}
    -
    -impl WalletSync for CompactFiltersBlockchain {
    -    #[allow(clippy::mutex_atomic)] // Mutex is easier to understand than a CAS loop.
    -    fn wallet_setup<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        let first_peer = &self.peers[0];
    -
    -        let skip_blocks = self.skip_blocks.unwrap_or(0);
    -
    -        let cf_sync = Arc::new(CfSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
    -
    -        let initial_height = self.headers.get_height()?;
    -        let total_bundles = (first_peer.get_version().start_height as usize)
    -            .checked_sub(skip_blocks)
    -            .map(|x| x / 1000)
    -            .unwrap_or(0)
    -            + 1;
    -        let expected_bundles_to_sync = total_bundles.saturating_sub(cf_sync.pruned_bundles()?);
    -
    -        let headers_cost = (first_peer.get_version().start_height as usize)
    -            .saturating_sub(initial_height) as f32
    -            * SYNC_HEADERS_COST;
    -        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
    -
    -        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
    -
    -        if let Some(snapshot) = sync::sync_headers(
    -            Arc::clone(first_peer),
    -            Arc::clone(&self.headers),
    -            |new_height| {
    -                let local_headers_cost =
    -                    new_height.saturating_sub(initial_height) as f32 * SYNC_HEADERS_COST;
    -                progress_update.update(
    -                    local_headers_cost / total_cost * 100.0,
    -                    Some(format!("Synced headers to {}", new_height)),
    -                )
    -            },
    -        )? {
    -            if snapshot.work()? > self.headers.work()? {
    -                info!("Applying snapshot with work: {}", snapshot.work()?);
    -                self.headers.apply_snapshot(snapshot)?;
    -            }
    -        }
    -
    -        let synced_height = self.headers.get_height()?;
    -        let buried_height = synced_height.saturating_sub(sync::BURIED_CONFIRMATIONS);
    -        info!("Synced headers to height: {}", synced_height);
    -
    -        cf_sync.prepare_sync(Arc::clone(first_peer))?;
    -
    -        let mut database = database.borrow_mut();
    -        let database = database.deref_mut();
    -
    -        let all_scripts = Arc::new(
    -            database
    -                .iter_script_pubkeys(None)?
    -                .into_iter()
    -                .map(|s| s.to_bytes())
    -                .collect::<Vec<_>>(),
    -        );
    -
    -        #[allow(clippy::mutex_atomic)]
    -        let last_synced_block = Arc::new(Mutex::new(synced_height));
    -
    -        let synced_bundles = Arc::new(AtomicUsize::new(0));
    -        let progress_update = Arc::new(Mutex::new(progress_update));
    -
    -        let mut threads = Vec::with_capacity(self.peers.len());
    -        for peer in &self.peers {
    -            let cf_sync = Arc::clone(&cf_sync);
    -            let peer = Arc::clone(peer);
    -            let headers = Arc::clone(&self.headers);
    -            let all_scripts = Arc::clone(&all_scripts);
    -            let last_synced_block = Arc::clone(&last_synced_block);
    -            let progress_update = Arc::clone(&progress_update);
    -            let synced_bundles = Arc::clone(&synced_bundles);
    -
    -            let thread = std::thread::spawn(move || {
    -                cf_sync.capture_thread_for_sync(
    -                    peer,
    -                    |block_hash, filter| {
    -                        if !filter
    -                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
    -                        {
    -                            return Ok(false);
    -                        }
    -
    -                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
    -                        let saved_correct_block = matches!(headers.get_full_block(block_height)?, Some(block) if &block.block_hash() == block_hash);
    -
    -                        if saved_correct_block {
    -                            Ok(false)
    -                        } else {
    -                            let mut last_synced_block = last_synced_block.lock().unwrap();
    -
    -                            // If we download a block older than `last_synced_block`, we update it so that
    -                            // we know to delete and re-process all txs starting from that height
    -                            if block_height < *last_synced_block {
    -                                *last_synced_block = block_height;
    -                            }
    -
    -                            Ok(true)
    -                        }
    -                    },
    -                    |index| {
    -                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
    -                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
    -                        progress_update.lock().unwrap().update(
    -                            (headers_cost + local_filters_cost) / total_cost * 100.0,
    -                            Some(format!(
    -                                "Synced filters {} - {}",
    -                                index * 1000 + 1,
    -                                (index + 1) * 1000
    -                            )),
    -                        )
    -                    },
    -                )
    -            });
    -
    -            threads.push(thread);
    -        }
    -
    -        for t in threads {
    -            t.join().unwrap()?;
    -        }
    -
    -        progress_update.lock().unwrap().update(
    -            (headers_cost + filters_cost) / total_cost * 100.0,
    -            Some("Processing downloaded blocks and mempool".into()),
    -        )?;
    -
    -        // delete all txs newer than last_synced_block
    -        let last_synced_block = *last_synced_block.lock().unwrap();
    -        log::debug!(
    -            "Dropping transactions newer than `last_synced_block` = {}",
    -            last_synced_block
    -        );
    -        let mut updates = database.begin_batch();
    -        for details in database.iter_txs(false)? {
    -            match details.confirmation_time {
    -                Some(c) if (c.height as usize) < last_synced_block => continue,
    -                _ => updates.del_tx(&details.txid, false)?,
    -            };
    -        }
    -        database.commit_batch(updates)?;
    -
    -        match first_peer.ask_for_mempool() {
    -            Err(CompactFiltersError::PeerBloomDisabled) => {
    -                log::warn!("Peer has BLOOM disabled, we can't ask for the mempool")
    -            }
    -            e => e?,
    -        };
    -
    -        let mut internal_max_deriv = None;
    -        let mut external_max_deriv = None;
    -
    -        for (height, block) in self.headers.iter_full_blocks()? {
    -            for tx in &block.txdata {
    -                self.process_tx(
    -                    database,
    -                    tx,
    -                    Some(height as u32),
    -                    None,
    -                    &mut internal_max_deriv,
    -                    &mut external_max_deriv,
    -                )?;
    -            }
    -        }
    -        for tx in first_peer.get_mempool().iter_txs().iter() {
    -            self.process_tx(
    -                database,
    -                tx,
    -                None,
    -                None,
    -                &mut internal_max_deriv,
    -                &mut external_max_deriv,
    -            )?;
    -        }
    -
    -        let current_ext = database
    -            .get_last_index(KeychainKind::External)?
    -            .unwrap_or(0);
    -        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_ext_new > current_ext {
    -            info!("Setting external index to {}", first_ext_new);
    -            database.set_last_index(KeychainKind::External, first_ext_new)?;
    -        }
    -
    -        let current_int = database
    -            .get_last_index(KeychainKind::Internal)?
    -            .unwrap_or(0);
    -        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_int_new > current_int {
    -            info!("Setting internal index to {}", first_int_new);
    -            database.set_last_index(KeychainKind::Internal, first_int_new)?;
    -        }
    -
    -        info!("Dropping blocks until {}", buried_height);
    -        self.headers.delete_blocks_until(buried_height)?;
    -
    -        progress_update
    -            .lock()
    -            .unwrap()
    -            .update(100.0, Some("Done".into()))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -/// Data to connect to a Bitcoin P2P peer
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq)]
    -pub struct BitcoinPeerConfig {
    -    /// Peer address such as 127.0.0.1:18333
    -    pub address: String,
    -    /// Optional socks5 proxy
    -    pub socks5: Option<String>,
    -    /// Optional socks5 proxy credentials
    -    pub socks5_credentials: Option<(String, String)>,
    -}
    -
    -/// Configuration for a [`CompactFiltersBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq)]
    -pub struct CompactFiltersBlockchainConfig {
    -    /// List of peers to try to connect to for asking headers and filters
    -    pub peers: Vec<BitcoinPeerConfig>,
    -    /// Network used
    -    pub network: Network,
    -    /// Storage dir to save partially downloaded headers and full blocks. Should be a separate directory per descriptor. Consider using [crate::wallet::wallet_name_from_descriptor] for this.
    -    pub storage_dir: String,
    -    /// Optionally skip initial `skip_blocks` blocks (default: 0)
    -    pub skip_blocks: Option<usize>,
    -}
    -
    -impl ConfigurableBlockchain for CompactFiltersBlockchain {
    -    type Config = CompactFiltersBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let mempool = Arc::new(Mempool::default());
    -        let peers = config
    -            .peers
    -            .iter()
    -            .map(|peer_conf| match &peer_conf.socks5 {
    -                None => Peer::connect(&peer_conf.address, Arc::clone(&mempool), config.network),
    -                Some(proxy) => Peer::connect_proxy(
    -                    peer_conf.address.as_str(),
    -                    proxy,
    -                    peer_conf
    -                        .socks5_credentials
    -                        .as_ref()
    -                        .map(|(a, b)| (a.as_str(), b.as_str())),
    -                    Arc::clone(&mempool),
    -                    config.network,
    -                ),
    -            })
    -            .collect::<Result<_, _>>()?;
    -
    -        Ok(CompactFiltersBlockchain::new(
    -            peers,
    -            &config.storage_dir,
    -            config.skip_blocks,
    -        )?)
    -    }
    -}
    -
    -/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
    -#[derive(Debug)]
    -pub enum CompactFiltersError {
    -    /// A peer sent an invalid or unexpected response
    -    InvalidResponse,
    -    /// The headers returned are invalid
    -    InvalidHeaders,
    -    /// The compact filter headers returned are invalid
    -    InvalidFilterHeader,
    -    /// The compact filter returned is invalid
    -    InvalidFilter,
    -    /// The peer is missing a block in the valid chain
    -    MissingBlock,
    -    /// Block hash at specified height not found
    -    BlockHashNotFound,
    -    /// The data stored in the block filters storage are corrupted
    -    DataCorruption,
    -
    -    /// A peer is not connected
    -    NotConnected,
    -    /// A peer took too long to reply to one of our messages
    -    Timeout,
    -    /// The peer doesn't advertise the [`BLOOM`](bitcoin::network::constants::ServiceFlags::BLOOM) service flag
    -    PeerBloomDisabled,
    -
    -    /// No peers have been specified
    -    NoPeers,
    -
    -    /// Internal database error
    -    Db(rocksdb::Error),
    -    /// Internal I/O error
    -    Io(std::io::Error),
    -    /// Invalid BIP158 filter
    -    Bip158(bitcoin::util::bip158::Error),
    -    /// Internal system time error
    -    Time(std::time::SystemTimeError),
    -
    -    /// Wrapper for [`crate::error::Error`]
    -    Global(Box<crate::error::Error>),
    -}
    -
    -impl fmt::Display for CompactFiltersError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        match self {
    -            Self::InvalidResponse => write!(f, "A peer sent an invalid or unexpected response"),
    -            Self::InvalidHeaders => write!(f, "Invalid headers"),
    -            Self::InvalidFilterHeader => write!(f, "Invalid filter header"),
    -            Self::InvalidFilter => write!(f, "Invalid filters"),
    -            Self::MissingBlock => write!(f, "The peer is missing a block in the valid chain"),
    -            Self::BlockHashNotFound => write!(f, "Block hash not found"),
    -            Self::DataCorruption => write!(
    -                f,
    -                "The data stored in the block filters storage are corrupted"
    -            ),
    -            Self::NotConnected => write!(f, "A peer is not connected"),
    -            Self::Timeout => write!(f, "A peer took too long to reply to one of our messages"),
    -            Self::PeerBloomDisabled => write!(f, "Peer doesn't advertise the BLOOM service flag"),
    -            Self::NoPeers => write!(f, "No peers have been specified"),
    -            Self::Db(err) => write!(f, "Internal database error: {}", err),
    -            Self::Io(err) => write!(f, "Internal I/O error: {}", err),
    -            Self::Bip158(err) => write!(f, "Invalid BIP158 filter: {}", err),
    -            Self::Time(err) => write!(f, "Invalid system time: {}", err),
    -            Self::Global(err) => write!(f, "Generic error: {}", err),
    -        }
    -    }
    -}
    -
    -impl std::error::Error for CompactFiltersError {}
    -
    -impl_error!(rocksdb::Error, Db, CompactFiltersError);
    -impl_error!(std::io::Error, Io, CompactFiltersError);
    -impl_error!(bitcoin::util::bip158::Error, Bip158, CompactFiltersError);
    -impl_error!(std::time::SystemTimeError, Time, CompactFiltersError);
    -
    -impl From<crate::error::Error> for CompactFiltersError {
    -    fn from(err: crate::error::Error) -> Self {
    -        CompactFiltersError::Global(Box::new(err))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html deleted file mode 100644 index 255e246efc..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html +++ /dev/null @@ -1,1155 +0,0 @@ -peer.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::collections::HashMap;
    -use std::io::BufReader;
    -use std::net::{TcpStream, ToSocketAddrs};
    -use std::sync::{Arc, Condvar, Mutex, RwLock};
    -use std::thread;
    -use std::time::{Duration, SystemTime, UNIX_EPOCH};
    -
    -use socks::{Socks5Stream, ToTargetAddr};
    -
    -use rand::{thread_rng, Rng};
    -
    -use bitcoin::consensus::{Decodable, Encodable};
    -use bitcoin::hash_types::BlockHash;
    -use bitcoin::network::constants::ServiceFlags;
    -use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
    -use bitcoin::network::message_blockdata::*;
    -use bitcoin::network::message_filter::*;
    -use bitcoin::network::message_network::VersionMessage;
    -use bitcoin::network::Address;
    -use bitcoin::{Block, Network, Transaction, Txid, Wtxid};
    -
    -use super::CompactFiltersError;
    -
    -type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
    -
    -pub(crate) const TIMEOUT_SECS: u64 = 30;
    -
    -/// Container for unconfirmed, but valid Bitcoin transactions
    -///
    -/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
    -/// duplicated in memory.
    -#[derive(Debug, Default)]
    -pub struct Mempool(RwLock<InnerMempool>);
    -
    -#[derive(Debug, Default)]
    -struct InnerMempool {
    -    txs: HashMap<Txid, Transaction>,
    -    wtxids: HashMap<Wtxid, Txid>,
    -}
    -
    -#[derive(Debug, Clone, PartialEq, Eq)]
    -enum TxIdentifier {
    -    Wtxid(Wtxid),
    -    Txid(Txid),
    -}
    -
    -impl Mempool {
    -    /// Create a new empty mempool
    -    pub fn new() -> Self {
    -        Self::default()
    -    }
    -
    -    /// Add a transaction to the mempool
    -    ///
    -    /// Note that this doesn't propagate the transaction to other
    -    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
    -    pub fn add_tx(&self, tx: Transaction) {
    -        let mut guard = self.0.write().unwrap();
    -
    -        guard.wtxids.insert(tx.wtxid(), tx.txid());
    -        guard.txs.insert(tx.txid(), tx);
    -    }
    -
    -    /// Look-up a transaction in the mempool given an [`Inventory`] request
    -    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
    -        let identifer = match inventory {
    -            Inventory::Error
    -            | Inventory::Block(_)
    -            | Inventory::WitnessBlock(_)
    -            | Inventory::CompactBlock(_) => return None,
    -            Inventory::Transaction(txid) => TxIdentifier::Txid(*txid),
    -            Inventory::WitnessTransaction(txid) => TxIdentifier::Txid(*txid),
    -            Inventory::WTx(wtxid) => TxIdentifier::Wtxid(*wtxid),
    -            Inventory::Unknown { inv_type, hash } => {
    -                log::warn!(
    -                    "Unknown inventory request type `{}`, hash `{:?}`",
    -                    inv_type,
    -                    hash
    -                );
    -                return None;
    -            }
    -        };
    -
    -        let txid = match identifer {
    -            TxIdentifier::Txid(txid) => Some(txid),
    -            TxIdentifier::Wtxid(wtxid) => self.0.read().unwrap().wtxids.get(&wtxid).cloned(),
    -        };
    -
    -        txid.and_then(|txid| self.0.read().unwrap().txs.get(&txid).cloned())
    -    }
    -
    -    /// Return whether or not the mempool contains a transaction with a given txid
    -    pub fn has_tx(&self, txid: &Txid) -> bool {
    -        self.0.read().unwrap().txs.contains_key(txid)
    -    }
    -
    -    /// Return the list of transactions contained in the mempool
    -    pub fn iter_txs(&self) -> Vec<Transaction> {
    -        self.0.read().unwrap().txs.values().cloned().collect()
    -    }
    -}
    -
    -/// A Bitcoin peer
    -#[derive(Debug)]
    -#[allow(dead_code)]
    -pub struct Peer {
    -    writer: Arc<Mutex<TcpStream>>,
    -    responses: Arc<RwLock<ResponsesMap>>,
    -
    -    reader_thread: thread::JoinHandle<()>,
    -    connected: Arc<RwLock<bool>>,
    -
    -    mempool: Arc<Mempool>,
    -
    -    version: VersionMessage,
    -    network: Network,
    -}
    -
    -impl Peer {
    -    /// Connect to a peer over a plaintext TCP connection
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](bitcoin::network::message::NetworkMessage::Ping)
    -    pub fn connect<A: ToSocketAddrs>(
    -        address: A,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let stream = TcpStream::connect(address)?;
    -
    -        Peer::from_stream(stream, mempool, network)
    -    }
    -
    -    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
    -    /// as a tuple of `(username, password)`
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
    -    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    -        target: T,
    -        proxy: P,
    -        credentials: Option<(&str, &str)>,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let socks_stream = if let Some((username, password)) = credentials {
    -            Socks5Stream::connect_with_password(proxy, target, username, password)?
    -        } else {
    -            Socks5Stream::connect(proxy, target)?
    -        };
    -
    -        Peer::from_stream(socks_stream.into_inner(), mempool, network)
    -    }
    -
    -    /// Create a [`Peer`] from an already connected TcpStream
    -    fn from_stream(
    -        stream: TcpStream,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let writer = Arc::new(Mutex::new(stream.try_clone()?));
    -        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
    -        let connected = Arc::new(RwLock::new(true));
    -
    -        let mut locked_writer = writer.lock().unwrap();
    -
    -        let reader_thread_responses = Arc::clone(&responses);
    -        let reader_thread_writer = Arc::clone(&writer);
    -        let reader_thread_mempool = Arc::clone(&mempool);
    -        let reader_thread_connected = Arc::clone(&connected);
    -        let reader_thread = thread::spawn(move || {
    -            Self::reader_thread(
    -                network,
    -                stream,
    -                reader_thread_responses,
    -                reader_thread_writer,
    -                reader_thread_mempool,
    -                reader_thread_connected,
    -            )
    -        });
    -
    -        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
    -        let nonce = thread_rng().gen();
    -        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
    -        let sender = Address {
    -            services: ServiceFlags::NONE,
    -            address: [0u16; 8],
    -            port: 0,
    -        };
    -
    -        Self::_send(
    -            &mut locked_writer,
    -            network.magic(),
    -            NetworkMessage::Version(VersionMessage::new(
    -                ServiceFlags::WITNESS,
    -                timestamp,
    -                receiver,
    -                sender,
    -                nonce,
    -                "MagicalBitcoinWallet".into(),
    -                0,
    -            )),
    -        )?;
    -        let version = if let NetworkMessage::Version(version) =
    -            Self::_recv(&responses, "version", None).unwrap()
    -        {
    -            version
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        };
    -
    -        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None).unwrap() {
    -            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        std::mem::drop(locked_writer);
    -
    -        Ok(Peer {
    -            writer,
    -            responses,
    -            reader_thread,
    -            connected,
    -            mempool,
    -            version,
    -            network,
    -        })
    -    }
    -
    -    /// Send a Bitcoin network message
    -    fn _send(
    -        writer: &mut TcpStream,
    -        magic: u32,
    -        payload: NetworkMessage,
    -    ) -> Result<(), CompactFiltersError> {
    -        log::trace!("==> {:?}", payload);
    -
    -        let raw_message = RawNetworkMessage { magic, payload };
    -
    -        raw_message
    -            .consensus_encode(writer)
    -            .map_err(|_| CompactFiltersError::DataCorruption)?;
    -
    -        Ok(())
    -    }
    -
    -    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
    -    fn _recv(
    -        responses: &Arc<RwLock<ResponsesMap>>,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Option<NetworkMessage> {
    -        let message_resp = {
    -            let mut lock = responses.write().unwrap();
    -            let message_resp = lock.entry(wait_for).or_default();
    -            Arc::clone(message_resp)
    -        };
    -
    -        let (lock, cvar) = &*message_resp;
    -
    -        let mut messages = lock.lock().unwrap();
    -        while messages.is_empty() {
    -            match timeout {
    -                None => messages = cvar.wait(messages).unwrap(),
    -                Some(t) => {
    -                    let result = cvar.wait_timeout(messages, t).unwrap();
    -                    if result.1.timed_out() {
    -                        return None;
    -                    }
    -                    messages = result.0;
    -                }
    -            }
    -        }
    -
    -        messages.pop()
    -    }
    -
    -    /// Return the [`VersionMessage`] sent by the peer
    -    pub fn get_version(&self) -> &VersionMessage {
    -        &self.version
    -    }
    -
    -    /// Return the Bitcoin [`Network`] in use
    -    pub fn get_network(&self) -> Network {
    -        self.network
    -    }
    -
    -    /// Return the mempool used by this peer
    -    pub fn get_mempool(&self) -> Arc<Mempool> {
    -        Arc::clone(&self.mempool)
    -    }
    -
    -    /// Return whether or not the peer is still connected
    -    pub fn is_connected(&self) -> bool {
    -        *self.connected.read().unwrap()
    -    }
    -
    -    /// Internal function called once the `reader_thread` is spawned
    -    fn reader_thread(
    -        network: Network,
    -        connection: TcpStream,
    -        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
    -        reader_thread_writer: Arc<Mutex<TcpStream>>,
    -        reader_thread_mempool: Arc<Mempool>,
    -        reader_thread_connected: Arc<RwLock<bool>>,
    -    ) {
    -        macro_rules! check_disconnect {
    -            ($call:expr) => {
    -                match $call {
    -                    Ok(good) => good,
    -                    Err(e) => {
    -                        log::debug!("Error {:?}", e);
    -                        *reader_thread_connected.write().unwrap() = false;
    -
    -                        break;
    -                    }
    -                }
    -            };
    -        }
    -
    -        let mut reader = BufReader::new(connection);
    -        loop {
    -            let raw_message: RawNetworkMessage =
    -                check_disconnect!(Decodable::consensus_decode(&mut reader));
    -
    -            let in_message = if raw_message.magic != network.magic() {
    -                continue;
    -            } else {
    -                raw_message.payload
    -            };
    -
    -            log::trace!("<== {:?}", in_message);
    -
    -            match in_message {
    -                NetworkMessage::Ping(nonce) => {
    -                    check_disconnect!(Self::_send(
    -                        &mut reader_thread_writer.lock().unwrap(),
    -                        network.magic(),
    -                        NetworkMessage::Pong(nonce),
    -                    ));
    -
    -                    continue;
    -                }
    -                NetworkMessage::Alert(_) => continue,
    -                NetworkMessage::GetData(ref inv) => {
    -                    let (found, not_found): (Vec<_>, Vec<_>) = inv
    -                        .iter()
    -                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
    -                        .partition(|(_, d)| d.is_some());
    -                    for (_, found_tx) in found {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::Tx(found_tx.unwrap()),
    -                        ));
    -                    }
    -
    -                    if !not_found.is_empty() {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::NotFound(
    -                                not_found.into_iter().map(|(i, _)| i).collect(),
    -                            ),
    -                        ));
    -                    }
    -                }
    -                _ => {}
    -            }
    -
    -            let message_resp = {
    -                let mut lock = reader_thread_responses.write().unwrap();
    -                let message_resp = lock.entry(in_message.cmd()).or_default();
    -                Arc::clone(message_resp)
    -            };
    -
    -            let (lock, cvar) = &*message_resp;
    -            let mut messages = lock.lock().unwrap();
    -            messages.push(in_message);
    -            cvar.notify_all();
    -        }
    -    }
    -
    -    /// Send a raw Bitcoin message to the peer
    -    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
    -        let mut writer = self.writer.lock().unwrap();
    -        Self::_send(&mut writer, self.network.magic(), payload)
    -    }
    -
    -    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
    -    pub fn recv(
    -        &self,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
    -        Ok(Self::_recv(&self.responses, wait_for, timeout))
    -    }
    -}
    -
    -pub trait CompactFiltersPeer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError>;
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError>;
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError>;
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
    -}
    -
    -impl CompactFiltersPeer for Peer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
    -            filter_type,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFCheckpt(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFHeaders(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
    -        let response = self
    -            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFilter(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFilters(GetCFilters {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -pub trait InvPeer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
    -}
    -
    -impl InvPeer for Peer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
    -        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
    -            block_hash,
    -        )]))?;
    -
    -        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
    -            None => Ok(None),
    -            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
    -            _ => Err(CompactFiltersError::InvalidResponse),
    -        }
    -    }
    -
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
    -        if !self.version.services.has(ServiceFlags::BLOOM) {
    -            return Err(CompactFiltersError::PeerBloomDisabled);
    -        }
    -
    -        self.send(NetworkMessage::MemPool)?;
    -        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
    -            None => return Ok(()), // empty mempool
    -            Some(NetworkMessage::Inv(inv)) => inv,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        let getdata = inv
    -            .iter()
    -            .cloned()
    -            .filter(
    -                |item| matches!(item, Inventory::Transaction(txid) if !self.mempool.has_tx(txid)),
    -            )
    -            .collect::<Vec<_>>();
    -        let num_txs = getdata.len();
    -        self.send(NetworkMessage::GetData(getdata))?;
    -
    -        for _ in 0..num_txs {
    -            let tx = self
    -                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -                .ok_or(CompactFiltersError::Timeout)?;
    -            let tx = match tx {
    -                NetworkMessage::Tx(tx) => tx,
    -                _ => return Err(CompactFiltersError::InvalidResponse),
    -            };
    -
    -            self.mempool.add_tx(tx);
    -        }
    -
    -        Ok(())
    -    }
    -
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
    -        self.mempool.add_tx(tx.clone());
    -        self.send(NetworkMessage::Tx(tx))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html deleted file mode 100644 index d0e781c31c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html +++ /dev/null @@ -1,1675 +0,0 @@ -store.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -658
    -659
    -660
    -661
    -662
    -663
    -664
    -665
    -666
    -667
    -668
    -669
    -670
    -671
    -672
    -673
    -674
    -675
    -676
    -677
    -678
    -679
    -680
    -681
    -682
    -683
    -684
    -685
    -686
    -687
    -688
    -689
    -690
    -691
    -692
    -693
    -694
    -695
    -696
    -697
    -698
    -699
    -700
    -701
    -702
    -703
    -704
    -705
    -706
    -707
    -708
    -709
    -710
    -711
    -712
    -713
    -714
    -715
    -716
    -717
    -718
    -719
    -720
    -721
    -722
    -723
    -724
    -725
    -726
    -727
    -728
    -729
    -730
    -731
    -732
    -733
    -734
    -735
    -736
    -737
    -738
    -739
    -740
    -741
    -742
    -743
    -744
    -745
    -746
    -747
    -748
    -749
    -750
    -751
    -752
    -753
    -754
    -755
    -756
    -757
    -758
    -759
    -760
    -761
    -762
    -763
    -764
    -765
    -766
    -767
    -768
    -769
    -770
    -771
    -772
    -773
    -774
    -775
    -776
    -777
    -778
    -779
    -780
    -781
    -782
    -783
    -784
    -785
    -786
    -787
    -788
    -789
    -790
    -791
    -792
    -793
    -794
    -795
    -796
    -797
    -798
    -799
    -800
    -801
    -802
    -803
    -804
    -805
    -806
    -807
    -808
    -809
    -810
    -811
    -812
    -813
    -814
    -815
    -816
    -817
    -818
    -819
    -820
    -821
    -822
    -823
    -824
    -825
    -826
    -827
    -828
    -829
    -830
    -831
    -832
    -833
    -834
    -835
    -836
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::convert::TryInto;
    -use std::fmt;
    -use std::io::{Read, Write};
    -use std::marker::PhantomData;
    -use std::sync::Arc;
    -use std::sync::RwLock;
    -
    -use rand::distributions::Alphanumeric;
    -use rand::{thread_rng, Rng};
    -
    -use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
    -
    -use bitcoin::blockdata::constants::genesis_block;
    -use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
    -use bitcoin::hash_types::{FilterHash, FilterHeader};
    -use bitcoin::hashes::Hash;
    -use bitcoin::util::bip158::BlockFilter;
    -use bitcoin::util::uint::Uint256;
    -use bitcoin::Block;
    -use bitcoin::BlockHash;
    -use bitcoin::BlockHeader;
    -use bitcoin::Network;
    -
    -use super::CompactFiltersError;
    -
    -pub trait StoreType: Default + fmt::Debug {}
    -
    -#[derive(Default, Debug)]
    -pub struct Full;
    -impl StoreType for Full {}
    -#[derive(Default, Debug)]
    -pub struct Snapshot;
    -impl StoreType for Snapshot {}
    -
    -pub enum StoreEntry {
    -    BlockHeader(Option<usize>),
    -    Block(Option<usize>),
    -    BlockHeaderIndex(Option<BlockHash>),
    -    CFilterTable((u8, Option<usize>)),
    -}
    -
    -impl StoreEntry {
    -    pub fn get_prefix(&self) -> Vec<u8> {
    -        match self {
    -            StoreEntry::BlockHeader(_) => b"z",
    -            StoreEntry::Block(_) => b"x",
    -            StoreEntry::BlockHeaderIndex(_) => b"i",
    -            StoreEntry::CFilterTable(_) => b"t",
    -        }
    -        .to_vec()
    -    }
    -
    -    pub fn get_key(&self) -> Vec<u8> {
    -        let mut prefix = self.get_prefix();
    -        match self {
    -            StoreEntry::BlockHeader(Some(height)) => {
    -                prefix.extend_from_slice(&height.to_be_bytes())
    -            }
    -            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
    -            StoreEntry::BlockHeaderIndex(Some(hash)) => {
    -                prefix.extend_from_slice(&hash.into_inner())
    -            }
    -            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
    -                prefix.push(*filter_type);
    -                if let Some(bundle_index) = bundle_index {
    -                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
    -                }
    -            }
    -            _ => {}
    -        }
    -
    -        prefix
    -    }
    -}
    -
    -pub trait SerializeDb: Sized {
    -    fn serialize(&self) -> Vec<u8>;
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
    -}
    -
    -impl<T> SerializeDb for T
    -where
    -    T: Encodable + Decodable,
    -{
    -    fn serialize(&self) -> Vec<u8> {
    -        serialize(self)
    -    }
    -
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
    -        deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)
    -    }
    -}
    -
    -impl Encodable for BundleStatus {
    -    fn consensus_encode<W: Write + ?Sized>(&self, e: &mut W) -> Result<usize, std::io::Error> {
    -        let mut written = 0;
    -
    -        match self {
    -            BundleStatus::Init => {
    -                written += 0x00u8.consensus_encode(e)?;
    -            }
    -            BundleStatus::CfHeaders { cf_headers } => {
    -                written += 0x01u8.consensus_encode(e)?;
    -                written += VarInt(cf_headers.len() as u64).consensus_encode(e)?;
    -                for header in cf_headers {
    -                    written += header.consensus_encode(e)?;
    -                }
    -            }
    -            BundleStatus::CFilters { cf_filters } => {
    -                written += 0x02u8.consensus_encode(e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(e)?;
    -                }
    -            }
    -            BundleStatus::Processed { cf_filters } => {
    -                written += 0x03u8.consensus_encode(e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(e)?;
    -                }
    -            }
    -            BundleStatus::Pruned => {
    -                written += 0x04u8.consensus_encode(e)?;
    -            }
    -            BundleStatus::Tip { cf_filters } => {
    -                written += 0x05u8.consensus_encode(e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(e)?;
    -                }
    -            }
    -        }
    -
    -        Ok(written)
    -    }
    -}
    -
    -impl Decodable for BundleStatus {
    -    fn consensus_decode<D: Read + ?Sized>(
    -        d: &mut D,
    -    ) -> Result<Self, bitcoin::consensus::encode::Error> {
    -        let byte_type = u8::consensus_decode(d)?;
    -        match byte_type {
    -            0x00 => Ok(BundleStatus::Init),
    -            0x01 => {
    -                let num = VarInt::consensus_decode(d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_headers = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_headers.push(FilterHeader::consensus_decode(d)?);
    -                }
    -
    -                Ok(BundleStatus::CfHeaders { cf_headers })
    -            }
    -            0x02 => {
    -                let num = VarInt::consensus_decode(d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(d)?);
    -                }
    -
    -                Ok(BundleStatus::CFilters { cf_filters })
    -            }
    -            0x03 => {
    -                let num = VarInt::consensus_decode(d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(d)?);
    -                }
    -
    -                Ok(BundleStatus::Processed { cf_filters })
    -            }
    -            0x04 => Ok(BundleStatus::Pruned),
    -            0x05 => {
    -                let num = VarInt::consensus_decode(d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(d)?);
    -                }
    -
    -                Ok(BundleStatus::Tip { cf_filters })
    -            }
    -            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
    -                "Invalid byte type",
    -            )),
    -        }
    -    }
    -}
    -
    -pub struct ChainStore<T: StoreType> {
    -    store: Arc<RwLock<DB>>,
    -    cf_name: String,
    -    min_height: usize,
    -    network: Network,
    -    phantom: PhantomData<T>,
    -}
    -
    -impl ChainStore<Full> {
    -    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
    -        let genesis = genesis_block(network);
    -
    -        let cf_name = "default".to_string();
    -        let cf_handle = store.cf_handle(&cf_name).unwrap();
    -
    -        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
    -
    -        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
    -            let mut batch = WriteBatch::default();
    -            batch.put_cf(
    -                cf_handle,
    -                genesis_key,
    -                (genesis.header, genesis.header.work()).serialize(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
    -                0usize.to_be_bytes(),
    -            );
    -            store.write(batch)?;
    -        }
    -
    -        Ok(ChainStore {
    -            store: Arc::new(RwLock::new(store)),
    -            cf_name,
    -            min_height: 0,
    -            network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
    -        let mut step = 1;
    -        let mut index = self.get_height()?;
    -        let mut answer = Vec::new();
    -
    -        let store_read = self.store.read().unwrap();
    -        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
    -
    -        loop {
    -            if answer.len() > 10 {
    -                step *= 2;
    -            }
    -
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -                &store_read
    -                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
    -                    .unwrap(),
    -            )?;
    -            answer.push((header.block_hash(), index));
    -
    -            if let Some(new_index) = index.checked_sub(step) {
    -                index = new_index;
    -            } else {
    -                break;
    -            }
    -        }
    -
    -        Ok(answer)
    -    }
    -
    -    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
    -        let new_cf_name: String = thread_rng()
    -            .sample_iter(&Alphanumeric)
    -            .map(|byte| byte as char)
    -            .take(16)
    -            .collect();
    -        let new_cf_name = format!("_headers:{}", new_cf_name);
    -
    -        let mut write_store = self.store.write().unwrap();
    -
    -        write_store.create_cf(&new_cf_name, &Default::default())?;
    -
    -        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
    -        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
    -
    -        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -            &write_store
    -                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -                .ok_or(CompactFiltersError::DataCorruption)?,
    -        )?;
    -
    -        let mut batch = WriteBatch::default();
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            from.to_be_bytes(),
    -        );
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeader(Some(from)).get_key(),
    -            (header, work).serialize(),
    -        );
    -        write_store.write(batch)?;
    -
    -        let store = Arc::clone(&self.store);
    -        Ok(ChainStore {
    -            store,
    -            cf_name: new_cf_name,
    -            min_height: from,
    -            network: self.network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
    -        let mut write_store = self.store.write().unwrap();
    -        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
    -
    -        let min_height = match iterator
    -            .next()
    -            .and_then(|(k, _)| k[1..].try_into().ok())
    -            .map(usize::from_be_bytes)
    -        {
    -            None => {
    -                std::mem::drop(iterator);
    -                write_store.drop_cf(cf_name).ok();
    -
    -                return Ok(());
    -            }
    -            Some(x) => x,
    -        };
    -        std::mem::drop(iterator);
    -        std::mem::drop(write_store);
    -
    -        let snapshot = ChainStore {
    -            store: Arc::clone(&self.store),
    -            cf_name: cf_name.into(),
    -            min_height,
    -            network: self.network,
    -            phantom: PhantomData,
    -        };
    -        if snapshot.work()? > self.work()? {
    -            self.apply_snapshot(snapshot)?;
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn apply_snapshot(
    -        &self,
    -        snaphost: ChainStore<Snapshot>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
    -
    -        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
    -
    -        let mut opts = ReadOptions::default();
    -        opts.set_iterate_upper_bound(to_key.clone());
    -
    -        log::debug!("Removing items");
    -        batch.delete_range_cf(cf_handle, &from_key, &to_key);
    -        for (_, v) in read_store.iterator_cf_opt(
    -            cf_handle,
    -            opts,
    -            IteratorMode::From(&from_key, Direction::Forward),
    -        ) {
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -            batch.delete_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            );
    -        }
    -
    -        // Delete full blocks overridden by snapshot
    -        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        log::debug!("Copying over new items");
    -        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
    -            batch.put_cf(cf_handle, k, v);
    -        }
    -
    -        read_store.write(batch)?;
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_height_for(
    -        &self,
    -        block_hash: &BlockHash,
    -    ) -> Result<Option<usize>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeaderIndex(Some(*block_hash)).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        data.map(|data| {
    -            Ok::<_, CompactFiltersError>(usize::from_be_bytes(
    -                data.as_ref()
    -                    .try_into()
    -                    .map_err(|_| CompactFiltersError::DataCorruption)?,
    -            ))
    -        })
    -        .transpose()
    -    }
    -
    -    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeader(Some(height)).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        data.map(|data| {
    -            let (header, _): (BlockHeader, Uint256) =
    -                deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
    -            Ok::<_, CompactFiltersError>(header.block_hash())
    -        })
    -        .transpose()
    -    }
    -
    -    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        self.store.read().unwrap().put(key, block.serialize())?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        let opt_block = read_store.get_pinned(key)?;
    -
    -        opt_block
    -            .map(|data| deserialize(&data))
    -            .transpose()
    -            .map_err(|_| CompactFiltersError::DataCorruption)
    -    }
    -
    -    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
    -        let from_key = StoreEntry::Block(Some(0)).get_key();
    -        let to_key = StoreEntry::Block(Some(height)).get_key();
    -
    -        let mut batch = WriteBatch::default();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        self.store.read().unwrap().write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::Block(None).get_key();
    -
    -        let iterator = read_store.prefix_iterator(&prefix);
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(k, v)| {
    -                let height: usize = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -                let block = SerializeDb::deserialize(&v)?;
    -
    -                Ok((height, block))
    -            })
    -            .collect::<Result<_, _>>()
    -    }
    -}
    -
    -impl<T: StoreType> ChainStore<T> {
    -    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(work)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(k, _)| -> Result<_, CompactFiltersError> {
    -                let height = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -
    -                Ok(height)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(header.block_hash())
    -            })
    -            .transpose()
    -    }
    -
    -    pub fn apply(
    -        &mut self,
    -        from: usize,
    -        headers: Vec<BlockHeader>,
    -    ) -> Result<BlockHash, CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let (mut last_hash, mut accumulated_work) = read_store
    -            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -            .map(|result| {
    -                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
    -                Ok::<_, CompactFiltersError>((header.block_hash(), work))
    -            })
    -            .transpose()?
    -            .ok_or(CompactFiltersError::DataCorruption)?;
    -
    -        for (index, header) in headers.into_iter().enumerate() {
    -            if header.prev_blockhash != last_hash {
    -                return Err(CompactFiltersError::InvalidHeaders);
    -            }
    -
    -            last_hash = header.block_hash();
    -            accumulated_work = accumulated_work + header.work();
    -
    -            let height = from + index + 1;
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -                (height).to_be_bytes(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeader(Some(height)).get_key(),
    -                (header, accumulated_work).serialize(),
    -            );
    -        }
    -
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().write(batch)?;
    -        Ok(last_hash)
    -    }
    -}
    -
    -impl<T: StoreType> fmt::Debug for ChainStore<T> {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
    -            .field("cf_name", &self.cf_name)
    -            .field("min_height", &self.min_height)
    -            .field("network", &self.network)
    -            .field("headers_height", &self.get_height())
    -            .field("tip_hash", &self.get_tip_hash())
    -            .finish()
    -    }
    -}
    -
    -pub enum BundleStatus {
    -    Init,
    -    CfHeaders { cf_headers: Vec<FilterHeader> },
    -    CFilters { cf_filters: Vec<Vec<u8>> },
    -    Processed { cf_filters: Vec<Vec<u8>> },
    -    Tip { cf_filters: Vec<Vec<u8>> },
    -    Pruned,
    -}
    -
    -pub struct CfStore {
    -    store: Arc<RwLock<DB>>,
    -    filter_type: u8,
    -}
    -
    -type BundleEntry = (BundleStatus, FilterHeader);
    -
    -impl CfStore {
    -    pub fn new(
    -        headers_store: &ChainStore<Full>,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = CfStore {
    -            store: Arc::clone(&headers_store.store),
    -            filter_type,
    -        };
    -
    -        let genesis = genesis_block(headers_store.network);
    -
    -        let filter = BlockFilter::new_script_filter(&genesis, |utxo| {
    -            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
    -        })?;
    -        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
    -
    -        // Add the genesis' filter
    -        {
    -            let read_store = cf_store.store.read().unwrap();
    -            if read_store.get_pinned(&first_key)?.is_none() {
    -                read_store.put(
    -                    &first_key,
    -                    (
    -                        BundleStatus::Init,
    -                        filter.filter_header(&FilterHeader::from_hash(Hash::all_zeros())),
    -                    )
    -                        .serialize(),
    -                )?;
    -            }
    -        }
    -
    -        Ok(cf_store)
    -    }
    -
    -    pub fn get_filter_type(&self) -> u8 {
    -        self.filter_type
    -    }
    -
    -    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(_, data)| BundleEntry::deserialize(&data))
    -            .collect::<Result<_, _>>()
    -    }
    -
    -    pub fn get_checkpoints(&self) -> Result<Vec<FilterHeader>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .skip(1)
    -            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
    -            .collect::<Result<_, _>>()
    -    }
    -
    -    pub fn replace_checkpoints(
    -        &self,
    -        checkpoints: Vec<FilterHeader>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let current_checkpoints = self.get_checkpoints()?;
    -
    -        let mut equal_bundles = 0;
    -        for (index, (our, their)) in current_checkpoints
    -            .iter()
    -            .zip(checkpoints.iter())
    -            .enumerate()
    -        {
    -            equal_bundles = index;
    -
    -            if our != their {
    -                break;
    -            }
    -        }
    -
    -        let read_store = self.store.read().unwrap();
    -        let mut batch = WriteBatch::default();
    -
    -        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
    -            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
    -
    -            if let Some((BundleStatus::Tip { .. }, _)) = read_store
    -                .get_pinned(&key)?
    -                .map(|data| BundleEntry::deserialize(&data))
    -                .transpose()?
    -            {
    -                println!("Keeping bundle #{} as Tip", index);
    -            } else {
    -                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
    -            }
    -        }
    -
    -        read_store.write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn advance_to_cf_headers(
    -        &self,
    -        bundle: usize,
    -        checkpoint: FilterHeader,
    -        filter_hashes: Vec<FilterHash>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let cf_headers: Vec<FilterHeader> = filter_hashes
    -            .into_iter()
    -            .scan(checkpoint, |prev_header, filter_hash| {
    -                let filter_header = filter_hash.filter_header(prev_header);
    -                *prev_header = filter_header;
    -
    -                Some(filter_header)
    -            })
    -            .collect();
    -
    -        let read_store = self.store.read().unwrap();
    -
    -        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
    -        if let Some((_, next_checkpoint)) = read_store
    -            .get_pinned(&next_key)?
    -            .map(|data| BundleEntry::deserialize(&data))
    -            .transpose()?
    -        {
    -            // check connection with the next bundle if present
    -            if cf_headers.iter().last() != Some(&next_checkpoint) {
    -                return Err(CompactFiltersError::InvalidFilterHeader);
    -            }
    -        }
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CfHeaders { cf_headers }, checkpoint);
    -
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn advance_to_cf_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint: FilterHeader,
    -        headers: Vec<FilterHeader>,
    -        filters: Vec<(usize, Vec<u8>)>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let cf_filters = filters
    -            .into_iter()
    -            .zip(headers.into_iter())
    -            .scan(checkpoint, |prev_header, ((_, filter_content), header)| {
    -                let filter = BlockFilter::new(&filter_content);
    -                if header != filter.filter_header(prev_header) {
    -                    return Some(Err(CompactFiltersError::InvalidFilter));
    -                }
    -                *prev_header = header;
    -
    -                Some(Ok::<_, CompactFiltersError>(filter_content))
    -            })
    -            .collect::<Result<_, _>>()?;
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CFilters { cf_filters }, checkpoint);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn prune_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint: FilterHeader,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Pruned, checkpoint);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn mark_as_tip(
    -        &self,
    -        bundle: usize,
    -        cf_filters: Vec<Vec<u8>>,
    -        checkpoint: FilterHeader,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Tip { cf_filters }, checkpoint);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html deleted file mode 100644 index 486cb9ade3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html +++ /dev/null @@ -1,597 +0,0 @@ -sync.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::collections::{BTreeMap, HashMap, VecDeque};
    -use std::sync::{Arc, Mutex};
    -use std::time::Duration;
    -
    -use bitcoin::hash_types::{BlockHash, FilterHeader};
    -use bitcoin::hashes::Hash;
    -use bitcoin::network::message::NetworkMessage;
    -use bitcoin::network::message_blockdata::GetHeadersMessage;
    -use bitcoin::util::bip158::BlockFilter;
    -
    -use super::peer::*;
    -use super::store::*;
    -use super::CompactFiltersError;
    -use crate::error::Error;
    -
    -pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
    -
    -pub struct CfSync {
    -    headers_store: Arc<ChainStore<Full>>,
    -    cf_store: Arc<CfStore>,
    -    skip_blocks: usize,
    -    bundles: Mutex<VecDeque<(BundleStatus, FilterHeader, usize)>>,
    -}
    -
    -impl CfSync {
    -    pub fn new(
    -        headers_store: Arc<ChainStore<Full>>,
    -        skip_blocks: usize,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = Arc::new(CfStore::new(&headers_store, filter_type)?);
    -
    -        Ok(CfSync {
    -            headers_store,
    -            cf_store,
    -            skip_blocks,
    -            bundles: Mutex::new(VecDeque::new()),
    -        })
    -    }
    -
    -    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
    -        Ok(self
    -            .cf_store
    -            .get_bundles()?
    -            .into_iter()
    -            .skip(self.skip_blocks / 1000)
    -            .fold(0, |acc, (status, _)| match status {
    -                BundleStatus::Pruned => acc + 1,
    -                _ => acc,
    -            }))
    -    }
    -
    -    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
    -        let mut bundles_lock = self.bundles.lock().unwrap();
    -
    -        let resp = peer.get_cf_checkpt(
    -            self.cf_store.get_filter_type(),
    -            self.headers_store.get_tip_hash()?.unwrap(),
    -        )?;
    -        self.cf_store.replace_checkpoints(resp.filter_headers)?;
    -
    -        bundles_lock.clear();
    -        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
    -            bundles_lock.push_back((status, checkpoint, index));
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn capture_thread_for_sync<F, Q>(
    -        &self,
    -        peer: Arc<Peer>,
    -        process: F,
    -        completed_bundle: Q,
    -    ) -> Result<(), CompactFiltersError>
    -    where
    -        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
    -        Q: Fn(usize) -> Result<(), Error>,
    -    {
    -        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
    -
    -        loop {
    -            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
    -                None => break,
    -                Some(x) => x,
    -            };
    -
    -            log::debug!(
    -                "Processing bundle #{} - height {} to {}",
    -                index,
    -                index * 1000 + 1,
    -                (index + 1) * 1000
    -            );
    -
    -            let process_received_filters =
    -                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
    -                    let mut filters_map = BTreeMap::new();
    -                    for _ in 0..expected_filters {
    -                        let filter = peer.pop_cf_filter_resp()?;
    -                        if filter.filter_type != self.cf_store.get_filter_type() {
    -                            return Err(CompactFiltersError::InvalidResponse);
    -                        }
    -
    -                        match self.headers_store.get_height_for(&filter.block_hash)? {
    -                            Some(height) => filters_map.insert(height, filter.filter),
    -                            None => return Err(CompactFiltersError::InvalidFilter),
    -                        };
    -                    }
    -
    -                    Ok(filters_map)
    -                };
    -
    -            let start_height = index * 1000 + 1;
    -            let mut already_processed = 0;
    -
    -            if start_height < self.skip_blocks {
    -                status = self.cf_store.prune_filters(index, checkpoint)?;
    -            }
    -
    -            let stop_height = std::cmp::min(current_height, start_height + 999);
    -            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
    -
    -            if let BundleStatus::Init = status {
    -                log::trace!("status: Init");
    -
    -                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                assert_eq!(resp.previous_filter_header, checkpoint);
    -                status =
    -                    self.cf_store
    -                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
    -            }
    -            if let BundleStatus::Tip { cf_filters } = status {
    -                log::trace!("status: Tip (beginning) ");
    -
    -                already_processed = cf_filters.len();
    -                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                let cf_headers = match self.cf_store.advance_to_cf_headers(
    -                    index,
    -                    checkpoint,
    -                    headers_resp.filter_hashes,
    -                )? {
    -                    BundleStatus::CfHeaders { cf_headers } => cf_headers,
    -                    _ => return Err(CompactFiltersError::InvalidResponse),
    -                };
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    (start_height + cf_filters.len()) as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
    -                let filters_map = process_received_filters(expected_filters)?;
    -                let filters = cf_filters
    -                    .into_iter()
    -                    .enumerate()
    -                    .chain(filters_map.into_iter())
    -                    .collect();
    -                status = self
    -                    .cf_store
    -                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
    -            }
    -            if let BundleStatus::CfHeaders { cf_headers } = status {
    -                log::trace!("status: CFHeaders");
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    start_height as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1;
    -                let filters_map = process_received_filters(expected_filters)?;
    -                status = self.cf_store.advance_to_cf_filters(
    -                    index,
    -                    checkpoint,
    -                    cf_headers,
    -                    filters_map.into_iter().collect(),
    -                )?;
    -            }
    -            if let BundleStatus::CFilters { cf_filters } = status {
    -                log::trace!("status: CFilters");
    -
    -                let last_sync_buried_height =
    -                    (start_height + already_processed).saturating_sub(BURIED_CONFIRMATIONS);
    -
    -                for (filter_index, filter) in cf_filters.iter().enumerate() {
    -                    let height = filter_index + start_height;
    -
    -                    // do not download blocks that were already "buried" since the last sync
    -                    if height < last_sync_buried_height {
    -                        continue;
    -                    }
    -
    -                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
    -
    -                    // TODO: also download random blocks?
    -                    if process(&block_hash, &BlockFilter::new(filter))? {
    -                        log::debug!("Downloading block {}", block_hash);
    -
    -                        let block = peer
    -                            .get_block(block_hash)?
    -                            .ok_or(CompactFiltersError::MissingBlock)?;
    -                        self.headers_store.save_full_block(&block, height)?;
    -                    }
    -                }
    -
    -                status = BundleStatus::Processed { cf_filters };
    -            }
    -            if let BundleStatus::Processed { cf_filters } = status {
    -                log::trace!("status: Processed");
    -
    -                if current_height - stop_height > 1000 {
    -                    status = self.cf_store.prune_filters(index, checkpoint)?;
    -                } else {
    -                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
    -                }
    -
    -                completed_bundle(index)?;
    -            }
    -            if let BundleStatus::Pruned = status {
    -                log::trace!("status: Pruned");
    -            }
    -            if let BundleStatus::Tip { .. } = status {
    -                log::trace!("status: Tip");
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -pub fn sync_headers<F>(
    -    peer: Arc<Peer>,
    -    store: Arc<ChainStore<Full>>,
    -    sync_fn: F,
    -) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
    -where
    -    F: Fn(usize) -> Result<(), Error>,
    -{
    -    let locators = store.get_locators()?;
    -    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
    -    let locators_map: HashMap<_, _> = locators.into_iter().collect();
    -
    -    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -        locators_vec,
    -        Hash::all_zeros(),
    -    )))?;
    -    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
    -        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -        .ok_or(CompactFiltersError::Timeout)?
    -    {
    -        if headers.is_empty() {
    -            return Ok(None);
    -        }
    -
    -        match locators_map.get(&headers[0].prev_blockhash) {
    -            None => return Err(CompactFiltersError::InvalidHeaders),
    -            Some(from) => (store.start_snapshot(*from)?, headers[0].prev_blockhash),
    -        }
    -    } else {
    -        return Err(CompactFiltersError::InvalidResponse);
    -    };
    -
    -    let mut sync_height = store.get_height()?;
    -    while sync_height < peer.get_version().start_height as usize {
    -        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -            vec![last_hash],
    -            Hash::all_zeros(),
    -        )))?;
    -        if let NetworkMessage::Headers(headers) = peer
    -            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?
    -        {
    -            let batch_len = headers.len();
    -            last_hash = snapshot.apply(sync_height, headers)?;
    -
    -            sync_height += batch_len;
    -            sync_fn(sync_height)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -    }
    -
    -    Ok(Some(snapshot))
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html deleted file mode 100644 index 12b18a8fd2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html +++ /dev/null @@ -1,867 +0,0 @@ -electrum.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Electrum
    -//!
    -//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
    -//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
    -//! querying the inner client.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::electrum::ElectrumBlockchain;
    -//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002")?;
    -//! let blockchain = ElectrumBlockchain::from(client);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::collections::{HashMap, HashSet};
    -use std::ops::{Deref, DerefMut};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::{Transaction, Txid};
    -
    -use electrum_client::{Client, ConfigBuilder, ElectrumApi, Socks5Config};
    -
    -use super::script_sync::Request;
    -use super::*;
    -use crate::database::{BatchDatabase, Database};
    -use crate::error::Error;
    -use crate::{BlockTime, FeeRate};
    -
    -/// Wrapper over an Electrum Client that implements the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
    -pub struct ElectrumBlockchain {
    -    client: Client,
    -    stop_gap: usize,
    -}
    -
    -impl std::convert::From<Client> for ElectrumBlockchain {
    -    fn from(client: Client) -> Self {
    -        ElectrumBlockchain {
    -            client,
    -            stop_gap: 20,
    -        }
    -    }
    -}
    -
    -impl Blockchain for ElectrumBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        Ok(self.client.transaction_broadcast(tx).map(|_| ())?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        Ok(FeeRate::from_btc_per_kvb(
    -            self.client.estimate_fee(target)? as f32
    -        ))
    -    }
    -}
    -
    -impl Deref for ElectrumBlockchain {
    -    type Target = Client;
    -
    -    fn deref(&self) -> &Self::Target {
    -        &self.client
    -    }
    -}
    -
    -impl StatelessBlockchain for ElectrumBlockchain {}
    -
    -impl GetHeight for ElectrumBlockchain {
    -    fn get_height(&self) -> Result<u32, Error> {
    -        // TODO: unsubscribe when added to the client, or is there a better call to use here?
    -
    -        Ok(self
    -            .client
    -            .block_headers_subscribe()
    -            .map(|data| data.height as u32)?)
    -    }
    -}
    -
    -impl GetTx for ElectrumBlockchain {
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.client.transaction_get(txid).map(Option::Some)?)
    -    }
    -}
    -
    -impl GetBlockHash for ElectrumBlockchain {
    -    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error> {
    -        let block_header = self.client.block_header(height as usize)?;
    -        Ok(block_header.block_hash())
    -    }
    -}
    -
    -impl WalletSync for ElectrumBlockchain {
    -    fn wallet_setup<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        _progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        let mut database = database.borrow_mut();
    -        let database = database.deref_mut();
    -        let mut request = script_sync::start(database, self.stop_gap)?;
    -        let mut block_times = HashMap::<u32, u32>::new();
    -        let mut txid_to_height = HashMap::<Txid, u32>::new();
    -        let mut tx_cache = TxCache::new(database, &self.client);
    -
    -        // Set chunk_size to the smallest value capable of finding a gap greater than stop_gap.
    -        let chunk_size = self.stop_gap + 1;
    -
    -        // The electrum server has been inconsistent somehow in its responses during sync. For
    -        // example, we do a batch request of transactions and the response contains less
    -        // tranascations than in the request. This should never happen but we don't want to panic.
    -        let electrum_goof = || Error::Generic("electrum server misbehaving".to_string());
    -
    -        let batch_update = loop {
    -            request = match request {
    -                Request::Script(script_req) => {
    -                    let scripts = script_req.request().take(chunk_size);
    -                    let txids_per_script: Vec<Vec<_>> = self
    -                        .client
    -                        .batch_script_get_history(scripts)
    -                        .map_err(Error::Electrum)?
    -                        .into_iter()
    -                        .map(|txs| {
    -                            txs.into_iter()
    -                                .map(|tx| {
    -                                    let tx_height = match tx.height {
    -                                        none if none <= 0 => None,
    -                                        height => {
    -                                            txid_to_height.insert(tx.tx_hash, height as u32);
    -                                            Some(height as u32)
    -                                        }
    -                                    };
    -                                    (tx.tx_hash, tx_height)
    -                                })
    -                                .collect()
    -                        })
    -                        .collect();
    -
    -                    script_req.satisfy(txids_per_script)?
    -                }
    -
    -                Request::Conftime(conftime_req) => {
    -                    // collect up to chunk_size heights to fetch from electrum
    -                    let needs_block_height = conftime_req
    -                        .request()
    -                        .filter_map(|txid| txid_to_height.get(txid).cloned())
    -                        .filter(|height| block_times.get(height).is_none())
    -                        .take(chunk_size)
    -                        .collect::<HashSet<u32>>();
    -
    -                    let new_block_headers = self
    -                        .client
    -                        .batch_block_header(needs_block_height.iter().cloned())?;
    -
    -                    for (height, header) in needs_block_height.into_iter().zip(new_block_headers) {
    -                        block_times.insert(height, header.time);
    -                    }
    -
    -                    let conftimes = conftime_req
    -                        .request()
    -                        .take(chunk_size)
    -                        .map(|txid| {
    -                            let confirmation_time = txid_to_height
    -                                .get(txid)
    -                                .map(|height| {
    -                                    let timestamp =
    -                                        *block_times.get(height).ok_or_else(electrum_goof)?;
    -                                    Result::<_, Error>::Ok(BlockTime {
    -                                        height: *height,
    -                                        timestamp: timestamp.into(),
    -                                    })
    -                                })
    -                                .transpose()?;
    -                            Ok(confirmation_time)
    -                        })
    -                        .collect::<Result<_, Error>>()?;
    -
    -                    conftime_req.satisfy(conftimes)?
    -                }
    -                Request::Tx(tx_req) => {
    -                    let needs_full = tx_req.request().take(chunk_size);
    -                    tx_cache.save_txs(needs_full.clone())?;
    -                    let full_transactions = needs_full
    -                        .map(|txid| tx_cache.get(*txid).ok_or_else(electrum_goof))
    -                        .collect::<Result<Vec<_>, _>>()?;
    -                    let input_txs = full_transactions.iter().flat_map(|tx| {
    -                        tx.input
    -                            .iter()
    -                            .filter(|input| !input.previous_output.is_null())
    -                            .map(|input| &input.previous_output.txid)
    -                    });
    -                    tx_cache.save_txs(input_txs)?;
    -
    -                    let full_details = full_transactions
    -                        .into_iter()
    -                        .map(|tx| {
    -                            let mut input_index = 0usize;
    -                            let prev_outputs = tx
    -                                .input
    -                                .iter()
    -                                .map(|input| {
    -                                    if input.previous_output.is_null() {
    -                                        return Ok(None);
    -                                    }
    -                                    let prev_tx = tx_cache
    -                                        .get(input.previous_output.txid)
    -                                        .ok_or_else(electrum_goof)?;
    -                                    let txout = prev_tx
    -                                        .output
    -                                        .get(input.previous_output.vout as usize)
    -                                        .ok_or_else(electrum_goof)?;
    -                                    input_index += 1;
    -                                    Ok(Some(txout.clone()))
    -                                })
    -                                .collect::<Result<Vec<_>, Error>>()?;
    -                            Ok((prev_outputs, tx))
    -                        })
    -                        .collect::<Result<Vec<_>, Error>>()?;
    -
    -                    tx_req.satisfy(full_details)?
    -                }
    -                Request::Finish(batch_update) => break batch_update,
    -            }
    -        };
    -
    -        database.commit_batch(batch_update)?;
    -        Ok(())
    -    }
    -}
    -
    -struct TxCache<'a, 'b, D> {
    -    db: &'a D,
    -    client: &'b Client,
    -    cache: HashMap<Txid, Transaction>,
    -}
    -
    -impl<'a, 'b, D: Database> TxCache<'a, 'b, D> {
    -    fn new(db: &'a D, client: &'b Client) -> Self {
    -        TxCache {
    -            db,
    -            client,
    -            cache: HashMap::default(),
    -        }
    -    }
    -    fn save_txs<'c>(&mut self, txids: impl Iterator<Item = &'c Txid>) -> Result<(), Error> {
    -        let mut need_fetch = vec![];
    -        for txid in txids {
    -            if self.cache.get(txid).is_some() {
    -                continue;
    -            } else if let Some(transaction) = self.db.get_raw_tx(txid)? {
    -                self.cache.insert(*txid, transaction);
    -            } else {
    -                need_fetch.push(txid);
    -            }
    -        }
    -
    -        if !need_fetch.is_empty() {
    -            let txs = self
    -                .client
    -                .batch_transaction_get(need_fetch.clone())
    -                .map_err(Error::Electrum)?;
    -            let mut txs: HashMap<_, _> = txs.into_iter().map(|tx| (tx.txid(), tx)).collect();
    -            for txid in need_fetch {
    -                if let Some(tx) = txs.remove(txid) {
    -                    self.cache.insert(*txid, tx);
    -                }
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -
    -    fn get(&self, txid: Txid) -> Option<Transaction> {
    -        self.cache.get(&txid).map(Clone::clone)
    -    }
    -}
    -
    -/// Configuration for an [`ElectrumBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq)]
    -pub struct ElectrumBlockchainConfig {
    -    /// URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with `ssl://` or `tcp://` and include a port
    -    ///
    -    /// eg. `ssl://electrum.blockstream.info:60002`
    -    pub url: String,
    -    /// URL of the socks5 proxy server or a Tor service
    -    pub socks5: Option<String>,
    -    /// Request retry count
    -    pub retry: u8,
    -    /// Request timeout (seconds)
    -    pub timeout: Option<u8>,
    -    /// Stop searching addresses for transactions after finding an unused gap of this length
    -    pub stop_gap: usize,
    -    /// Validate the domain when using SSL
    -    pub validate_domain: bool,
    -}
    -
    -impl ConfigurableBlockchain for ElectrumBlockchain {
    -    type Config = ElectrumBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let socks5 = config.socks5.as_ref().map(Socks5Config::new);
    -        let electrum_config = ConfigBuilder::new()
    -            .retry(config.retry)
    -            .timeout(config.timeout)?
    -            .socks5(socks5)?
    -            .validate_domain(config.validate_domain)
    -            .build();
    -
    -        Ok(ElectrumBlockchain {
    -            client: Client::from_config(config.url.as_str(), electrum_config)?,
    -            stop_gap: config.stop_gap,
    -        })
    -    }
    -}
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-electrum")]
    -mod test {
    -    use std::sync::Arc;
    -
    -    use super::*;
    -    use crate::database::MemoryDatabase;
    -    use crate::testutils::blockchain_tests::TestClient;
    -    use crate::testutils::configurable_blockchain_tests::ConfigurableBlockchainTester;
    -    use crate::wallet::{AddressIndex, Wallet};
    -
    -    crate::bdk_blockchain_tests! {
    -        fn test_instance(test_client: &TestClient) -> ElectrumBlockchain {
    -            ElectrumBlockchain::from(Client::new(&test_client.electrsd.electrum_url).unwrap())
    -        }
    -    }
    -
    -    fn get_factory() -> (TestClient, Arc<ElectrumBlockchain>) {
    -        let test_client = TestClient::default();
    -
    -        let factory = Arc::new(ElectrumBlockchain::from(
    -            Client::new(&test_client.electrsd.electrum_url).unwrap(),
    -        ));
    -
    -        (test_client, factory)
    -    }
    -
    -    #[test]
    -    fn test_electrum_blockchain_factory() {
    -        let (_test_client, factory) = get_factory();
    -
    -        let a = factory.build("aaaaaa", None).unwrap();
    -        let b = factory.build("bbbbbb", None).unwrap();
    -
    -        assert_eq!(
    -            a.client.block_headers_subscribe().unwrap().height,
    -            b.client.block_headers_subscribe().unwrap().height
    -        );
    -    }
    -
    -    #[test]
    -    fn test_electrum_blockchain_factory_sync_wallet() {
    -        let (mut test_client, factory) = get_factory();
    -
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new(
    -            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
    -            None,
    -            bitcoin::Network::Regtest,
    -            db,
    -        )
    -        .unwrap();
    -
    -        let address = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let tx = testutils! {
    -            @tx ( (@addr address.address) => 50_000 )
    -        };
    -        test_client.receive(tx);
    -
    -        factory
    -            .sync_wallet(&wallet, None, Default::default())
    -            .unwrap();
    -
    -        assert_eq!(wallet.get_balance().unwrap().untrusted_pending, 50_000);
    -    }
    -
    -    #[test]
    -    fn test_electrum_with_variable_configs() {
    -        struct ElectrumTester;
    -
    -        impl ConfigurableBlockchainTester<ElectrumBlockchain> for ElectrumTester {
    -            const BLOCKCHAIN_NAME: &'static str = "Electrum";
    -
    -            fn config_with_stop_gap(
    -                &self,
    -                test_client: &mut TestClient,
    -                stop_gap: usize,
    -            ) -> Option<ElectrumBlockchainConfig> {
    -                Some(ElectrumBlockchainConfig {
    -                    url: test_client.electrsd.electrum_url.clone(),
    -                    socks5: None,
    -                    retry: 0,
    -                    timeout: None,
    -                    stop_gap: stop_gap,
    -                    validate_domain: true,
    -                })
    -            }
    -        }
    -
    -        ElectrumTester.run();
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/blocking.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/blocking.rs.html deleted file mode 100644 index 45b765e0f6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/blocking.rs.html +++ /dev/null @@ -1,485 +0,0 @@ -blocking.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Esplora by way of `ureq` HTTP client.
    -
    -use std::collections::{HashMap, HashSet};
    -use std::ops::DerefMut;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::{Transaction, Txid};
    -
    -use esplora_client::{convert_fee_rate, BlockingClient, Builder, Tx};
    -
    -use crate::blockchain::*;
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -/// Structure that implements the logic to sync with Esplora
    -///
    -/// ## Example
    -/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
    -#[derive(Debug)]
    -pub struct EsploraBlockchain {
    -    url_client: BlockingClient,
    -    stop_gap: usize,
    -    concurrency: u8,
    -}
    -
    -impl EsploraBlockchain {
    -    /// Create a new instance of the client from a base URL and the `stop_gap`.
    -    pub fn new(base_url: &str, stop_gap: usize) -> Self {
    -        let url_client = Builder::new(base_url)
    -            .build_blocking()
    -            .expect("Should never fail with no proxy and timeout");
    -
    -        Self::from_client(url_client, stop_gap)
    -    }
    -
    -    /// Build a new instance given a client
    -    pub fn from_client(url_client: BlockingClient, stop_gap: usize) -> Self {
    -        EsploraBlockchain {
    -            url_client,
    -            concurrency: super::DEFAULT_CONCURRENT_REQUESTS,
    -            stop_gap,
    -        }
    -    }
    -
    -    /// Set the number of parallel requests the client can make.
    -    pub fn with_concurrency(mut self, concurrency: u8) -> Self {
    -        self.concurrency = concurrency;
    -        self
    -    }
    -}
    -
    -impl Blockchain for EsploraBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        self.url_client.broadcast(tx)?;
    -        Ok(())
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        let estimates = self.url_client.get_fee_estimates()?;
    -        Ok(FeeRate::from_sat_per_vb(convert_fee_rate(
    -            target, estimates,
    -        )?))
    -    }
    -}
    -
    -impl Deref for EsploraBlockchain {
    -    type Target = BlockingClient;
    -
    -    fn deref(&self) -> &Self::Target {
    -        &self.url_client
    -    }
    -}
    -
    -impl StatelessBlockchain for EsploraBlockchain {}
    -
    -impl GetHeight for EsploraBlockchain {
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(self.url_client.get_height()?)
    -    }
    -}
    -
    -impl GetTx for EsploraBlockchain {
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.url_client.get_tx(txid)?)
    -    }
    -}
    -
    -impl GetBlockHash for EsploraBlockchain {
    -    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error> {
    -        Ok(self.url_client.get_block_hash(height as u32)?)
    -    }
    -}
    -
    -impl WalletSync for EsploraBlockchain {
    -    fn wallet_setup<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        _progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        use crate::blockchain::script_sync::Request;
    -        let mut database = database.borrow_mut();
    -        let database = database.deref_mut();
    -        let mut request = script_sync::start(database, self.stop_gap)?;
    -        let mut tx_index: HashMap<Txid, Tx> = HashMap::new();
    -        let batch_update = loop {
    -            request = match request {
    -                Request::Script(script_req) => {
    -                    let scripts = script_req
    -                        .request()
    -                        .take(self.concurrency as usize)
    -                        .cloned();
    -
    -                    let mut handles = vec![];
    -                    for script in scripts {
    -                        let client = self.url_client.clone();
    -                        // make each request in its own thread.
    -                        handles.push(std::thread::spawn(move || {
    -                            let mut related_txs: Vec<Tx> = client.scripthash_txs(&script, None)?;
    -
    -                            let n_confirmed =
    -                                related_txs.iter().filter(|tx| tx.status.confirmed).count();
    -                            // esplora pages on 25 confirmed transactions. If there's 25 or more we
    -                            // keep requesting to see if there's more.
    -                            if n_confirmed >= 25 {
    -                                loop {
    -                                    let new_related_txs: Vec<Tx> = client.scripthash_txs(
    -                                        &script,
    -                                        Some(related_txs.last().unwrap().txid),
    -                                    )?;
    -                                    let n = new_related_txs.len();
    -                                    related_txs.extend(new_related_txs);
    -                                    // we've reached the end
    -                                    if n < 25 {
    -                                        break;
    -                                    }
    -                                }
    -                            }
    -                            Result::<_, Error>::Ok(related_txs)
    -                        }));
    -                    }
    -
    -                    let txs_per_script: Vec<Vec<Tx>> = handles
    -                        .into_iter()
    -                        .map(|handle| handle.join().unwrap())
    -                        .collect::<Result<_, _>>()?;
    -                    let mut satisfaction = vec![];
    -
    -                    for txs in txs_per_script {
    -                        satisfaction.push(
    -                            txs.iter()
    -                                .map(|tx| (tx.txid, tx.status.block_height))
    -                                .collect(),
    -                        );
    -                        for tx in txs {
    -                            tx_index.insert(tx.txid, tx);
    -                        }
    -                    }
    -
    -                    script_req.satisfy(satisfaction)?
    -                }
    -                Request::Conftime(conftime_req) => {
    -                    let conftimes = conftime_req
    -                        .request()
    -                        .map(|txid| {
    -                            tx_index
    -                                .get(txid)
    -                                .expect("must be in index")
    -                                .confirmation_time()
    -                                .map(Into::into)
    -                        })
    -                        .collect();
    -                    conftime_req.satisfy(conftimes)?
    -                }
    -                Request::Tx(tx_req) => {
    -                    let full_txs = tx_req
    -                        .request()
    -                        .map(|txid| {
    -                            let tx = tx_index.get(txid).expect("must be in index");
    -                            Ok((tx.previous_outputs(), tx.to_tx()))
    -                        })
    -                        .collect::<Result<_, Error>>()?;
    -                    tx_req.satisfy(full_txs)?
    -                }
    -                Request::Finish(batch_update) => break batch_update,
    -            }
    -        };
    -
    -        database.commit_batch(batch_update)?;
    -
    -        Ok(())
    -    }
    -}
    -
    -impl ConfigurableBlockchain for EsploraBlockchain {
    -    type Config = super::EsploraBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let mut builder = Builder::new(config.base_url.as_str());
    -
    -        if let Some(timeout) = config.timeout {
    -            builder = builder.timeout(timeout);
    -        }
    -
    -        if let Some(proxy) = &config.proxy {
    -            builder = builder.proxy(proxy);
    -        }
    -
    -        let mut blockchain =
    -            EsploraBlockchain::from_client(builder.build_blocking()?, config.stop_gap);
    -
    -        if let Some(concurrency) = config.concurrency {
    -            blockchain = blockchain.with_concurrency(concurrency);
    -        }
    -
    -        Ok(blockchain)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html deleted file mode 100644 index dcda425833..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html +++ /dev/null @@ -1,263 +0,0 @@ -mod.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -
    //! Esplora
    -//!
    -//! This module defines a [`EsploraBlockchain`] struct that can query an Esplora
    -//! backend populate the wallet's [database](crate::database::Database) by:
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::esplora::EsploraBlockchain;
    -//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", 20);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -//!
    -//! Esplora blockchain can use either `ureq` or `reqwest` for the HTTP client
    -//! depending on your needs (blocking or async respectively).
    -//!
    -//! Please note, to configure the Esplora HTTP client correctly use one of:
    -//! Blocking:  --features='use-esplora-blocking'
    -//! Async:     --features='async-interface,use-esplora-async' --no-default-features
    -
    -pub use esplora_client::Error as EsploraError;
    -
    -#[cfg(feature = "use-esplora-async")]
    -mod r#async;
    -
    -#[cfg(feature = "use-esplora-async")]
    -pub use self::r#async::*;
    -
    -#[cfg(feature = "use-esplora-blocking")]
    -mod blocking;
    -
    -#[cfg(feature = "use-esplora-blocking")]
    -pub use self::blocking::*;
    -
    -/// Configuration for an [`EsploraBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq)]
    -pub struct EsploraBlockchainConfig {
    -    /// Base URL of the esplora service
    -    ///
    -    /// eg. `https://blockstream.info/api/`
    -    pub base_url: String,
    -    /// Optional URL of the proxy to use to make requests to the Esplora server
    -    ///
    -    /// The string should be formatted as: `<protocol>://<user>:<password>@host:<port>`.
    -    ///
    -    /// Note that the format of this value and the supported protocols change slightly between the
    -    /// sync version of esplora (using `ureq`) and the async version (using `reqwest`). For more
    -    /// details check with the documentation of the two crates. Both of them are compiled with
    -    /// the `socks` feature enabled.
    -    ///
    -    /// The proxy is ignored when targeting `wasm32`.
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub proxy: Option<String>,
    -    /// Number of parallel requests sent to the esplora service (default: 4)
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub concurrency: Option<u8>,
    -    /// Stop searching addresses for transactions after finding an unused gap of this length.
    -    pub stop_gap: usize,
    -    /// Socket timeout.
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub timeout: Option<u64>,
    -}
    -
    -impl EsploraBlockchainConfig {
    -    /// create a config with default values given the base url and stop gap
    -    pub fn new(base_url: String, stop_gap: usize) -> Self {
    -        Self {
    -            base_url,
    -            proxy: None,
    -            timeout: None,
    -            stop_gap,
    -            concurrency: None,
    -        }
    -    }
    -}
    -
    -impl From<esplora_client::BlockTime> for crate::BlockTime {
    -    fn from(esplora_client::BlockTime { timestamp, height }: esplora_client::BlockTime) -> Self {
    -        Self { timestamp, height }
    -    }
    -}
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-esplora")]
    -crate::bdk_blockchain_tests! {
    -    fn test_instance(test_client: &TestClient) -> EsploraBlockchain {
    -        EsploraBlockchain::new(&format!("http://{}",test_client.electrsd.esplora_url.as_ref().unwrap()), 20)
    -    }
    -}
    -
    -const DEFAULT_CONCURRENT_REQUESTS: u8 = 4;
    -
    -#[cfg(test)]
    -mod test {
    -    #[test]
    -    #[cfg(feature = "test-esplora")]
    -    fn test_esplora_with_variable_configs() {
    -        use super::*;
    -
    -        use crate::testutils::{
    -            blockchain_tests::TestClient,
    -            configurable_blockchain_tests::ConfigurableBlockchainTester,
    -        };
    -
    -        struct EsploraTester;
    -
    -        impl ConfigurableBlockchainTester<EsploraBlockchain> for EsploraTester {
    -            const BLOCKCHAIN_NAME: &'static str = "Esplora";
    -
    -            fn config_with_stop_gap(
    -                &self,
    -                test_client: &mut TestClient,
    -                stop_gap: usize,
    -            ) -> Option<EsploraBlockchainConfig> {
    -                Some(EsploraBlockchainConfig {
    -                    base_url: format!(
    -                        "http://{}",
    -                        test_client.electrsd.esplora_url.as_ref().unwrap()
    -                    ),
    -                    proxy: None,
    -                    concurrency: None,
    -                    stop_gap: stop_gap,
    -                    timeout: None,
    -                })
    -            }
    -        }
    -
    -        EsploraTester.run();
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html deleted file mode 100644 index cd2bf65780..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html +++ /dev/null @@ -1,785 +0,0 @@ -mod.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Blockchain backends
    -//!
    -//! This module provides the implementation of a few commonly-used backends like
    -//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
    -//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
    -//! [`Blockchain`] that can be implemented to build customized backends.
    -
    -use std::cell::RefCell;
    -use std::collections::HashSet;
    -use std::ops::Deref;
    -use std::sync::mpsc::{channel, Receiver, Sender};
    -use std::sync::Arc;
    -
    -use bitcoin::{BlockHash, Transaction, Txid};
    -
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::wallet::{wallet_name_from_descriptor, Wallet};
    -use crate::{FeeRate, KeychainKind};
    -
    -#[cfg(any(
    -    feature = "electrum",
    -    feature = "esplora",
    -    feature = "compact_filters",
    -    feature = "rpc"
    -))]
    -pub mod any;
    -mod script_sync;
    -
    -#[cfg(any(
    -    feature = "electrum",
    -    feature = "esplora",
    -    feature = "compact_filters",
    -    feature = "rpc"
    -))]
    -pub use any::{AnyBlockchain, AnyBlockchainConfig};
    -
    -#[cfg(feature = "electrum")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -pub mod electrum;
    -#[cfg(feature = "electrum")]
    -pub use self::electrum::ElectrumBlockchain;
    -#[cfg(feature = "electrum")]
    -pub use self::electrum::ElectrumBlockchainConfig;
    -
    -#[cfg(feature = "rpc")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
    -pub mod rpc;
    -#[cfg(feature = "rpc")]
    -pub use self::rpc::RpcBlockchain;
    -#[cfg(feature = "rpc")]
    -pub use self::rpc::RpcConfig;
    -
    -#[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;
    -
    -/// Capabilities that can be supported by a [`Blockchain`] backend
    -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    -pub enum Capability {
    -    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
    -    FullHistory,
    -    /// Can fetch any historical transaction given its txid
    -    GetAnyTx,
    -    /// Can compute accurate fees for the transactions found during sync
    -    AccurateFees,
    -}
    -
    -/// Trait that defines the actions that must be supported by a blockchain backend
    -#[maybe_async]
    -pub trait Blockchain: WalletSync + GetHeight + GetTx + GetBlockHash {
    -    /// Return the set of [`Capability`] supported by this backend
    -    fn get_capabilities(&self) -> HashSet<Capability>;
    -    /// Broadcast a transaction
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
    -    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
    -}
    -
    -/// Trait for getting the current height of the blockchain.
    -#[maybe_async]
    -pub trait GetHeight {
    -    /// Return the current height
    -    fn get_height(&self) -> Result<u32, Error>;
    -}
    -
    -#[maybe_async]
    -/// Trait for getting a transaction by txid
    -pub trait GetTx {
    -    /// Fetch a transaction given its txid
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -}
    -
    -#[maybe_async]
    -/// Trait for getting block hash by block height
    -pub trait GetBlockHash {
    -    /// fetch block hash given its height
    -    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error>;
    -}
    -
    -/// Trait for blockchains that can sync by updating the database directly.
    -#[maybe_async]
    -pub trait WalletSync {
    -    /// Setup the backend and populate the internal database for the first time
    -    ///
    -    /// This method is the equivalent of [`Self::wallet_sync`], but it's guaranteed to only be
    -    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
    -    ///
    -    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
    -    /// might need to perform specific actions only the first time they are synced.
    -    ///
    -    /// For types that do not have that distinction, only this method can be implemented, since
    -    /// [`WalletSync::wallet_sync`] defaults to calling this internally if not overridden.
    -    /// Populate the internal database with transactions and UTXOs
    -    fn wallet_setup<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error>;
    -
    -    /// If not overridden, it defaults to calling [`Self::wallet_setup`] internally.
    -    ///
    -    /// This method should implement the logic required to iterate over the list of the wallet's
    -    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
    -    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
    -    /// [`BatchOperations::set_utxo`].
    -    ///
    -    /// This method should also take care of removing UTXOs that are seen as spent in the
    -    /// blockchain, using [`BatchOperations::del_utxo`].
    -    ///
    -    /// The `progress_update` object can be used to give the caller updates about the progress by using
    -    /// [`Progress::update`].
    -    ///
    -    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
    -    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
    -    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
    -    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
    -    fn wallet_sync<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.wallet_setup(database, progress_update))
    -    }
    -}
    -
    -/// Trait for [`Blockchain`] types that can be created given a configuration
    -pub trait ConfigurableBlockchain: Blockchain + Sized {
    -    /// Type that contains the configuration
    -    type Config: std::fmt::Debug;
    -
    -    /// Create a new instance given a configuration
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    -
    -/// Trait for blockchains that don't contain any state
    -///
    -/// Statless blockchains can be used to sync multiple wallets with different descriptors.
    -///
    -/// [`BlockchainFactory`] is automatically implemented for `Arc<T>` where `T` is a stateless
    -/// blockchain.
    -pub trait StatelessBlockchain: Blockchain {}
    -
    -/// Trait for a factory of blockchains that share the underlying connection or configuration
    -#[cfg_attr(
    -    not(feature = "async-interface"),
    -    doc = r##"
    -## Example
    -
    -This example shows how to sync multiple walles and return the sum of their balances
    -
    -```no_run
    -# use bdk::Error;
    -# use bdk::blockchain::*;
    -# use bdk::database::*;
    -# use bdk::wallet::*;
    -# use bdk::*;
    -fn sum_of_balances<B: BlockchainFactory>(blockchain_factory: B, wallets: &[Wallet<MemoryDatabase>]) -> Result<Balance, Error> {
    -    Ok(wallets
    -        .iter()
    -        .map(|w| -> Result<_, Error> {
    -            blockchain_factory.sync_wallet(&w, None, SyncOptions::default())?;
    -            w.get_balance()
    -        })
    -        .collect::<Result<Vec<_>, _>>()?
    -        .into_iter()
    -        .sum())
    -}
    -```
    -"##
    -)]
    -pub trait BlockchainFactory {
    -    /// The type returned when building a blockchain from this factory
    -    type Inner: Blockchain;
    -
    -    /// Build a new blockchain for the given descriptor wallet_name
    -    ///
    -    /// If `override_skip_blocks` is `None`, the returned blockchain will inherit the number of blocks
    -    /// from the factory. Since it's not possible to override the value to `None`, set it to
    -    /// `Some(0)` to rescan from the genesis.
    -    fn build(
    -        &self,
    -        wallet_name: &str,
    -        override_skip_blocks: Option<u32>,
    -    ) -> Result<Self::Inner, Error>;
    -
    -    /// Build a new blockchain for a given wallet
    -    ///
    -    /// Internally uses [`wallet_name_from_descriptor`] to derive the name, and then calls
    -    /// [`BlockchainFactory::build`] to create the blockchain instance.
    -    fn build_for_wallet<D: BatchDatabase>(
    -        &self,
    -        wallet: &Wallet<D>,
    -        override_skip_blocks: Option<u32>,
    -    ) -> Result<Self::Inner, Error> {
    -        let wallet_name = wallet_name_from_descriptor(
    -            wallet.public_descriptor(KeychainKind::External)?.unwrap(),
    -            wallet.public_descriptor(KeychainKind::Internal)?,
    -            wallet.network(),
    -            wallet.secp_ctx(),
    -        )?;
    -        self.build(&wallet_name, override_skip_blocks)
    -    }
    -
    -    /// Use [`BlockchainFactory::build_for_wallet`] to get a blockchain, then sync the wallet
    -    ///
    -    /// This can be used when a new blockchain would only be used to sync a wallet and then
    -    /// immediately dropped. Keep in mind that specific blockchain factories may perform slow
    -    /// operations to build a blockchain for a given wallet, so if a wallet needs to be synced
    -    /// often it's recommended to use [`BlockchainFactory::build_for_wallet`] to reuse the same
    -    /// blockchain multiple times.
    -    #[cfg(not(feature = "async-interface"))]
    -    #[cfg_attr(docsrs, doc(cfg(not(feature = "async-interface"))))]
    -    fn sync_wallet<D: BatchDatabase>(
    -        &self,
    -        wallet: &Wallet<D>,
    -        override_skip_blocks: Option<u32>,
    -        sync_options: crate::wallet::SyncOptions,
    -    ) -> Result<(), Error> {
    -        let blockchain = self.build_for_wallet(wallet, override_skip_blocks)?;
    -        wallet.sync(&blockchain, sync_options)
    -    }
    -}
    -
    -impl<T: StatelessBlockchain> BlockchainFactory for Arc<T> {
    -    type Inner = Self;
    -
    -    fn build(&self, _wallet_name: &str, _override_skip_blocks: Option<u32>) -> Result<Self, Error> {
    -        Ok(Arc::clone(self))
    -    }
    -}
    -
    -/// Data sent with a progress update over a [`channel`]
    -pub type ProgressData = (f32, Option<String>);
    -
    -/// Trait for types that can receive and process progress updates during [`WalletSync::wallet_sync`] and
    -/// [`WalletSync::wallet_setup`]
    -pub trait Progress: Send + 'static + core::fmt::Debug {
    -    /// Send a new progress update
    -    ///
    -    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
    -    /// optional text message that can be displayed to the user.
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
    -}
    -
    -/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
    -pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
    -    channel()
    -}
    -
    -impl Progress for Sender<ProgressData> {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        if !(0.0..=100.0).contains(&progress) {
    -            return Err(Error::InvalidProgressValue(progress));
    -        }
    -
    -        self.send((progress, message))
    -            .map_err(|_| Error::ProgressUpdateError)
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and drops every update received
    -#[derive(Clone, Copy, Default, Debug)]
    -pub struct NoopProgress;
    -
    -/// Create a new instance of [`NoopProgress`]
    -pub fn noop_progress() -> NoopProgress {
    -    NoopProgress
    -}
    -
    -impl Progress for NoopProgress {
    -    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
    -        Ok(())
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and logs at level `INFO` every update received
    -#[derive(Clone, Copy, Default, Debug)]
    -pub struct LogProgress;
    -
    -/// Create a new instance of [`LogProgress`]
    -pub fn log_progress() -> LogProgress {
    -    LogProgress
    -}
    -
    -impl Progress for LogProgress {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        log::info!(
    -            "Sync {:.3}%: `{}`",
    -            progress,
    -            message.unwrap_or_else(|| "".into())
    -        );
    -
    -        Ok(())
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: Blockchain> Blockchain for Arc<T> {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        maybe_await!(self.deref().get_capabilities())
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        maybe_await!(self.deref().broadcast(tx))
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        maybe_await!(self.deref().estimate_fee(target))
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: GetTx> GetTx for Arc<T> {
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        maybe_await!(self.deref().get_tx(txid))
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: GetHeight> GetHeight for Arc<T> {
    -    fn get_height(&self) -> Result<u32, Error> {
    -        maybe_await!(self.deref().get_height())
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: GetBlockHash> GetBlockHash for Arc<T> {
    -    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error> {
    -        maybe_await!(self.deref().get_block_hash(height))
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: WalletSync> WalletSync for Arc<T> {
    -    fn wallet_setup<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().wallet_setup(database, progress_update))
    -    }
    -
    -    fn wallet_sync<D: BatchDatabase>(
    -        &self,
    -        database: &RefCell<D>,
    -        progress_update: Box<dyn Progress>,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().wallet_sync(database, progress_update))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/rpc.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/rpc.rs.html deleted file mode 100644 index 17ea16fbf9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/rpc.rs.html +++ /dev/null @@ -1,2009 +0,0 @@ -rpc.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -658
    -659
    -660
    -661
    -662
    -663
    -664
    -665
    -666
    -667
    -668
    -669
    -670
    -671
    -672
    -673
    -674
    -675
    -676
    -677
    -678
    -679
    -680
    -681
    -682
    -683
    -684
    -685
    -686
    -687
    -688
    -689
    -690
    -691
    -692
    -693
    -694
    -695
    -696
    -697
    -698
    -699
    -700
    -701
    -702
    -703
    -704
    -705
    -706
    -707
    -708
    -709
    -710
    -711
    -712
    -713
    -714
    -715
    -716
    -717
    -718
    -719
    -720
    -721
    -722
    -723
    -724
    -725
    -726
    -727
    -728
    -729
    -730
    -731
    -732
    -733
    -734
    -735
    -736
    -737
    -738
    -739
    -740
    -741
    -742
    -743
    -744
    -745
    -746
    -747
    -748
    -749
    -750
    -751
    -752
    -753
    -754
    -755
    -756
    -757
    -758
    -759
    -760
    -761
    -762
    -763
    -764
    -765
    -766
    -767
    -768
    -769
    -770
    -771
    -772
    -773
    -774
    -775
    -776
    -777
    -778
    -779
    -780
    -781
    -782
    -783
    -784
    -785
    -786
    -787
    -788
    -789
    -790
    -791
    -792
    -793
    -794
    -795
    -796
    -797
    -798
    -799
    -800
    -801
    -802
    -803
    -804
    -805
    -806
    -807
    -808
    -809
    -810
    -811
    -812
    -813
    -814
    -815
    -816
    -817
    -818
    -819
    -820
    -821
    -822
    -823
    -824
    -825
    -826
    -827
    -828
    -829
    -830
    -831
    -832
    -833
    -834
    -835
    -836
    -837
    -838
    -839
    -840
    -841
    -842
    -843
    -844
    -845
    -846
    -847
    -848
    -849
    -850
    -851
    -852
    -853
    -854
    -855
    -856
    -857
    -858
    -859
    -860
    -861
    -862
    -863
    -864
    -865
    -866
    -867
    -868
    -869
    -870
    -871
    -872
    -873
    -874
    -875
    -876
    -877
    -878
    -879
    -880
    -881
    -882
    -883
    -884
    -885
    -886
    -887
    -888
    -889
    -890
    -891
    -892
    -893
    -894
    -895
    -896
    -897
    -898
    -899
    -900
    -901
    -902
    -903
    -904
    -905
    -906
    -907
    -908
    -909
    -910
    -911
    -912
    -913
    -914
    -915
    -916
    -917
    -918
    -919
    -920
    -921
    -922
    -923
    -924
    -925
    -926
    -927
    -928
    -929
    -930
    -931
    -932
    -933
    -934
    -935
    -936
    -937
    -938
    -939
    -940
    -941
    -942
    -943
    -944
    -945
    -946
    -947
    -948
    -949
    -950
    -951
    -952
    -953
    -954
    -955
    -956
    -957
    -958
    -959
    -960
    -961
    -962
    -963
    -964
    -965
    -966
    -967
    -968
    -969
    -970
    -971
    -972
    -973
    -974
    -975
    -976
    -977
    -978
    -979
    -980
    -981
    -982
    -983
    -984
    -985
    -986
    -987
    -988
    -989
    -990
    -991
    -992
    -993
    -994
    -995
    -996
    -997
    -998
    -999
    -1000
    -1001
    -1002
    -1003
    -
    // Bitcoin Dev Kit
    -// Written in 2021 by Riccardo Casatta <riccardo@casatta.it>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Rpc Blockchain
    -//!
    -//! Backend that gets blockchain data from Bitcoin Core RPC
    -//!
    -//! This is an **EXPERIMENTAL** feature, API and other major changes are expected.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::{RpcConfig, RpcBlockchain, ConfigurableBlockchain, rpc::Auth};
    -//! let config = RpcConfig {
    -//!     url: "127.0.0.1:18332".to_string(),
    -//!     auth: Auth::Cookie {
    -//!         file: "/home/user/.bitcoin/.cookie".into(),
    -//!     },
    -//!     network: bdk::bitcoin::Network::Testnet,
    -//!     wallet_name: "wallet_name".to_string(),
    -//!     sync_params: None,
    -//! };
    -//! let blockchain = RpcBlockchain::from_config(&config);
    -//! ```
    -
    -use crate::bitcoin::hashes::hex::ToHex;
    -use crate::bitcoin::{Network, OutPoint, Transaction, TxOut, Txid};
    -use crate::blockchain::*;
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::descriptor::calc_checksum;
    -use crate::error::MissingCachedScripts;
    -use crate::{BlockTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails};
    -use bitcoin::Script;
    -use bitcoincore_rpc::json::{
    -    GetTransactionResultDetailCategory, ImportMultiOptions, ImportMultiRequest,
    -    ImportMultiRequestScriptPubkey, ImportMultiRescanSince, ListTransactionResult,
    -    ListUnspentResultEntry, ScanningDetails,
    -};
    -use bitcoincore_rpc::jsonrpc::serde_json::{json, Value};
    -use bitcoincore_rpc::Auth as RpcAuth;
    -use bitcoincore_rpc::{Client, RpcApi};
    -use log::{debug, info};
    -use serde::{Deserialize, Serialize};
    -use std::cell::RefCell;
    -use std::collections::{HashMap, HashSet};
    -use std::ops::{Deref, DerefMut};
    -use std::path::PathBuf;
    -use std::thread;
    -use std::time::Duration;
    -
    -/// The main struct for RPC backend implementing the [crate::blockchain::Blockchain] trait
    -#[derive(Debug)]
    -pub struct RpcBlockchain {
    -    /// Rpc client to the node, includes the wallet name
    -    client: Client,
    -    /// Whether the wallet is a "descriptor" or "legacy" wallet in Core
    -    is_descriptors: bool,
    -    /// Blockchain capabilities, cached here at startup
    -    capabilities: HashSet<Capability>,
    -    /// Sync parameters.
    -    sync_params: RpcSyncParams,
    -}
    -
    -impl Deref for RpcBlockchain {
    -    type Target = Client;
    -
    -    fn deref(&self) -> &Self::Target {
    -        &self.client
    -    }
    -}
    -
    -/// RpcBlockchain configuration options
    -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
    -pub struct RpcConfig {
    -    /// The bitcoin node url
    -    pub url: String,
    -    /// The bitcoin node authentication mechanism
    -    pub auth: Auth,
    -    /// The network we are using (it will be checked the bitcoin node network matches this)
    -    pub network: Network,
    -    /// The wallet name in the bitcoin node, consider using [crate::wallet::wallet_name_from_descriptor] for this
    -    pub wallet_name: String,
    -    /// Sync parameters
    -    pub sync_params: Option<RpcSyncParams>,
    -}
    -
    -/// Sync parameters for Bitcoin Core RPC.
    -///
    -/// In general, BDK tries to sync `scriptPubKey`s cached in [`crate::database::Database`] with
    -/// `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining
    -/// how the `importdescriptors` RPC calls are to be made.
    -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
    -pub struct RpcSyncParams {
    -    /// The minimum number of scripts to scan for on initial sync.
    -    pub start_script_count: usize,
    -    /// Time in unix seconds in which initial sync will start scanning from (0 to start from genesis).
    -    pub start_time: u64,
    -    /// Forces every sync to use `start_time` as import timestamp.
    -    pub force_start_time: bool,
    -    /// RPC poll rate (in seconds) to get state updates.
    -    pub poll_rate_sec: u64,
    -}
    -
    -impl Default for RpcSyncParams {
    -    fn default() -> Self {
    -        Self {
    -            start_script_count: 100,
    -            start_time: 0,
    -            force_start_time: false,
    -            poll_rate_sec: 3,
    -        }
    -    }
    -}
    -
    -/// This struct is equivalent to [bitcoincore_rpc::Auth] but it implements [serde::Serialize]
    -/// To be removed once upstream equivalent is implementing Serialize (json serialization format
    -/// should be the same), see [rust-bitcoincore-rpc/pull/181](https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/181)
    -#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
    -#[serde(rename_all = "snake_case")]
    -#[serde(untagged)]
    -pub enum Auth {
    -    /// None authentication
    -    None,
    -    /// Authentication with username and password, usually [Auth::Cookie] should be preferred
    -    UserPass {
    -        /// Username
    -        username: String,
    -        /// Password
    -        password: String,
    -    },
    -    /// Authentication with a cookie file
    -    Cookie {
    -        /// Cookie file
    -        file: PathBuf,
    -    },
    -}
    -
    -impl From<Auth> for RpcAuth {
    -    fn from(auth: Auth) -> Self {
    -        match auth {
    -            Auth::None => RpcAuth::None,
    -            Auth::UserPass { username, password } => RpcAuth::UserPass(username, password),
    -            Auth::Cookie { file } => RpcAuth::CookieFile(file),
    -        }
    -    }
    -}
    -
    -impl Blockchain for RpcBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        self.capabilities.clone()
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        Ok(self.client.send_raw_transaction(tx).map(|_| ())?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        let sat_per_kb = self
    -            .client
    -            .estimate_smart_fee(target as u16, None)?
    -            .fee_rate
    -            .ok_or(Error::FeeRateUnavailable)?
    -            .to_sat() as f64;
    -
    -        Ok(FeeRate::from_sat_per_vb((sat_per_kb / 1000f64) as f32))
    -    }
    -}
    -
    -impl GetTx for RpcBlockchain {
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(Some(self.client.get_raw_transaction(txid, None)?))
    -    }
    -}
    -
    -impl GetHeight for RpcBlockchain {
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(self.client.get_blockchain_info().map(|i| i.blocks as u32)?)
    -    }
    -}
    -
    -impl GetBlockHash for RpcBlockchain {
    -    fn get_block_hash(&self, height: u64) -> Result<BlockHash, Error> {
    -        Ok(self.client.get_block_hash(height)?)
    -    }
    -}
    -
    -impl WalletSync for RpcBlockchain {
    -    fn wallet_setup<D>(&self, db: &RefCell<D>, prog: Box<dyn Progress>) -> Result<(), Error>
    -    where
    -        D: BatchDatabase,
    -    {
    -        let mut db = db.borrow_mut();
    -        let db = db.deref_mut();
    -        let batch = DbState::new(db, &self.sync_params, &*prog)?
    -            .sync_with_core(&self.client, self.is_descriptors)?
    -            .as_db_batch()?;
    -
    -        db.commit_batch(batch)
    -    }
    -}
    -
    -impl ConfigurableBlockchain for RpcBlockchain {
    -    type Config = RpcConfig;
    -
    -    /// Returns RpcBlockchain backend creating an RPC client to a specific wallet named as the descriptor's checksum
    -    /// if it's the first time it creates the wallet in the node and upon return is granted the wallet is loaded
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let wallet_url = format!("{}/wallet/{}", config.url, &config.wallet_name);
    -
    -        let client = Client::new(wallet_url.as_str(), config.auth.clone().into())?;
    -        let rpc_version = client.version()?;
    -
    -        info!("connected to '{}' with auth: {:?}", wallet_url, config.auth);
    -
    -        if client.list_wallets()?.contains(&config.wallet_name) {
    -            info!("wallet already loaded: {}", config.wallet_name);
    -        } else if list_wallet_dir(&client)?.contains(&config.wallet_name) {
    -            client.load_wallet(&config.wallet_name)?;
    -            info!("wallet loaded: {}", config.wallet_name);
    -        } else {
    -            // pre-0.21 use legacy wallets
    -            if rpc_version < 210_000 {
    -                client.create_wallet(&config.wallet_name, Some(true), None, None, None)?;
    -            } else {
    -                // TODO: move back to api call when https://github.com/rust-bitcoin/rust-bitcoincore-rpc/issues/225 is closed
    -                let args = [
    -                    Value::String(config.wallet_name.clone()),
    -                    Value::Bool(true),
    -                    Value::Bool(false),
    -                    Value::Null,
    -                    Value::Bool(false),
    -                    Value::Bool(true),
    -                ];
    -                let _: Value = client.call("createwallet", &args)?;
    -            }
    -
    -            info!("wallet created: {}", config.wallet_name);
    -        }
    -
    -        let is_descriptors = is_wallet_descriptor(&client)?;
    -
    -        let blockchain_info = client.get_blockchain_info()?;
    -        let network = match blockchain_info.chain.as_str() {
    -            "main" => Network::Bitcoin,
    -            "test" => Network::Testnet,
    -            "regtest" => Network::Regtest,
    -            "signet" => Network::Signet,
    -            _ => return Err(Error::Generic("Invalid network".to_string())),
    -        };
    -        if network != config.network {
    -            return Err(Error::InvalidNetwork {
    -                requested: config.network,
    -                found: network,
    -            });
    -        }
    -
    -        let mut capabilities: HashSet<_> = vec![Capability::FullHistory].into_iter().collect();
    -        if rpc_version >= 210_000 {
    -            let info: HashMap<String, Value> = client.call("getindexinfo", &[]).unwrap();
    -            if info.contains_key("txindex") {
    -                capabilities.insert(Capability::GetAnyTx);
    -                capabilities.insert(Capability::AccurateFees);
    -            }
    -        }
    -
    -        Ok(RpcBlockchain {
    -            client,
    -            capabilities,
    -            is_descriptors,
    -            sync_params: config.sync_params.clone().unwrap_or_default(),
    -        })
    -    }
    -}
    -
    -/// return the wallets available in default wallet directory
    -//TODO use bitcoincore_rpc method when PR #179 lands
    -fn list_wallet_dir(client: &Client) -> Result<Vec<String>, Error> {
    -    #[derive(Deserialize)]
    -    struct Name {
    -        name: String,
    -    }
    -    #[derive(Deserialize)]
    -    struct CallResult {
    -        wallets: Vec<Name>,
    -    }
    -
    -    let result: CallResult = client.call("listwalletdir", &[])?;
    -    Ok(result.wallets.into_iter().map(|n| n.name).collect())
    -}
    -
    -/// Represents the state of the [`crate::database::Database`].
    -struct DbState<'a, D> {
    -    db: &'a D,
    -    params: &'a RpcSyncParams,
    -    prog: &'a dyn Progress,
    -
    -    ext_spks: Vec<Script>,
    -    int_spks: Vec<Script>,
    -    txs: HashMap<Txid, TransactionDetails>,
    -    utxos: HashSet<LocalUtxo>,
    -    last_indexes: HashMap<KeychainKind, u32>,
    -
    -    // "deltas" to apply to database
    -    retained_txs: HashSet<Txid>, // txs to retain (everything else should be deleted)
    -    updated_txs: HashSet<Txid>,  // txs to update
    -    updated_utxos: HashSet<LocalUtxo>, // utxos to update
    -}
    -
    -impl<'a, D: BatchDatabase> DbState<'a, D> {
    -    /// Obtain [DbState] from [crate::database::Database].
    -    fn new(db: &'a D, params: &'a RpcSyncParams, prog: &'a dyn Progress) -> Result<Self, Error> {
    -        let ext_spks = db.iter_script_pubkeys(Some(KeychainKind::External))?;
    -        let int_spks = db.iter_script_pubkeys(Some(KeychainKind::Internal))?;
    -
    -        // This is a hack to see whether atleast one of the keychains comes from a derivable
    -        // descriptor. We assume that non-derivable descriptors always has a script count of 1.
    -        let last_count = std::cmp::max(ext_spks.len(), int_spks.len());
    -        let has_derivable = last_count > 1;
    -
    -        // If at least one descriptor is derivable, we need to ensure scriptPubKeys are sufficiently
    -        // cached.
    -        if has_derivable && last_count < params.start_script_count {
    -            let inner_err = MissingCachedScripts {
    -                last_count,
    -                missing_count: params.start_script_count - last_count,
    -            };
    -            debug!("requesting more spks with: {:?}", inner_err);
    -            return Err(Error::MissingCachedScripts(inner_err));
    -        }
    -
    -        let txs = db
    -            .iter_txs(true)?
    -            .into_iter()
    -            .map(|tx| (tx.txid, tx))
    -            .collect::<HashMap<_, _>>();
    -
    -        let utxos = db.iter_utxos()?.into_iter().collect::<HashSet<_>>();
    -
    -        let last_indexes = [KeychainKind::External, KeychainKind::Internal]
    -            .iter()
    -            .filter_map(|keychain| match db.get_last_index(*keychain) {
    -                Ok(li_opt) => li_opt.map(|li| Ok((*keychain, li))),
    -                Err(err) => Some(Err(err)),
    -            })
    -            .collect::<Result<HashMap<_, _>, Error>>()?;
    -
    -        info!("initial db state: txs={} utxos={}", txs.len(), utxos.len());
    -
    -        // "delta" fields
    -        let retained_txs = HashSet::with_capacity(txs.len());
    -        let updated_txs = HashSet::with_capacity(txs.len());
    -        let updated_utxos = HashSet::with_capacity(utxos.len());
    -
    -        Ok(Self {
    -            db,
    -            params,
    -            prog,
    -            ext_spks,
    -            int_spks,
    -            txs,
    -            utxos,
    -            last_indexes,
    -            retained_txs,
    -            updated_txs,
    -            updated_utxos,
    -        })
    -    }
    -
    -    /// Sync states of [BatchDatabase] and Core wallet.
    -    /// First we import all `scriptPubKey`s from database into core wallet
    -    fn sync_with_core(&mut self, client: &Client, is_descriptor: bool) -> Result<&mut Self, Error> {
    -        // this tells Core wallet where to sync from for imported scripts
    -        let start_epoch = if self.params.force_start_time {
    -            self.params.start_time
    -        } else {
    -            self.db
    -                .get_sync_time()?
    -                .map_or(self.params.start_time, |st| st.block_time.timestamp)
    -        };
    -
    -        // sync scriptPubKeys from Database to Core wallet
    -        let scripts_iter = self.ext_spks.iter().chain(&self.int_spks);
    -        if is_descriptor {
    -            import_descriptors(client, start_epoch, scripts_iter)?;
    -        } else {
    -            import_multi(client, start_epoch, scripts_iter)?;
    -        }
    -
    -        // wait for Core wallet to rescan (TODO: maybe make this async)
    -        await_wallet_scan(client, self.params.poll_rate_sec, self.prog)?;
    -
    -        // obtain iterator of pagenated `listtransactions` RPC calls
    -        const LIST_TX_PAGE_SIZE: usize = 100; // item count per page
    -        let tx_iter = list_transactions(client, LIST_TX_PAGE_SIZE)?.filter(|item| {
    -            // filter out conflicting transactions - only accept transactions that are already
    -            // confirmed, or exists in mempool
    -            item.info.confirmations > 0 || client.get_mempool_entry(&item.info.txid).is_ok()
    -        });
    -
    -        // iterate through chronological results of `listtransactions`
    -        for tx_res in tx_iter {
    -            let mut updated = false;
    -
    -            let db_tx = self.txs.entry(tx_res.info.txid).or_insert_with(|| {
    -                updated = true;
    -                TransactionDetails {
    -                    txid: tx_res.info.txid,
    -                    transaction: None,
    -
    -                    received: 0,
    -                    sent: 0,
    -                    fee: None,
    -                    confirmation_time: None,
    -                }
    -            });
    -
    -            // update raw tx (if needed)
    -            let raw_tx =
    -                &*match &mut db_tx.transaction {
    -                    Some(raw_tx) => raw_tx,
    -                    db_tx_opt => {
    -                        updated = true;
    -                        db_tx_opt.insert(client.get_raw_transaction(
    -                            &tx_res.info.txid,
    -                            tx_res.info.blockhash.as_ref(),
    -                        )?)
    -                    }
    -                };
    -
    -            // update fee (if needed)
    -            if let (None, Some(new_fee)) = (db_tx.fee, tx_res.detail.fee) {
    -                updated = true;
    -                db_tx.fee = Some(new_fee.to_sat().unsigned_abs());
    -            }
    -
    -            // update confirmation time (if needed)
    -            let conf_time = BlockTime::new(tx_res.info.blockheight, tx_res.info.blocktime);
    -            if db_tx.confirmation_time != conf_time {
    -                updated = true;
    -                db_tx.confirmation_time = conf_time;
    -            }
    -
    -            // update received (if needed)
    -            let received = Self::received_from_raw_tx(self.db, raw_tx)?;
    -            if db_tx.received != received {
    -                updated = true;
    -                db_tx.received = received;
    -            }
    -
    -            // check if tx has an immature coinbase output (add to updated UTXOs)
    -            // this is required because `listunspent` does not include immature coinbase outputs
    -            if tx_res.detail.category == GetTransactionResultDetailCategory::Immature {
    -                let txout = raw_tx
    -                    .output
    -                    .get(tx_res.detail.vout as usize)
    -                    .cloned()
    -                    .ok_or_else(|| {
    -                        Error::Generic(format!(
    -                            "Core RPC returned detail with invalid vout '{}' for tx '{}'",
    -                            tx_res.detail.vout, tx_res.info.txid,
    -                        ))
    -                    })?;
    -
    -                if let Some((keychain, index)) =
    -                    self.db.get_path_from_script_pubkey(&txout.script_pubkey)?
    -                {
    -                    let utxo = LocalUtxo {
    -                        outpoint: OutPoint::new(tx_res.info.txid, tx_res.detail.vout),
    -                        txout,
    -                        keychain,
    -                        is_spent: false,
    -                    };
    -                    self.updated_utxos.insert(utxo);
    -                    self.update_last_index(keychain, index);
    -                }
    -            }
    -
    -            // update tx deltas
    -            self.retained_txs.insert(tx_res.info.txid);
    -            if updated {
    -                self.updated_txs.insert(tx_res.info.txid);
    -            }
    -        }
    -
    -        // obtain vector of `TransactionDetails::sent` changes
    -        let sent_updates = self
    -            .txs
    -            .values()
    -            // only bother to update txs that are retained
    -            .filter(|db_tx| self.retained_txs.contains(&db_tx.txid))
    -            // only bother to update txs where the raw tx is accessable
    -            .filter_map(|db_tx| (db_tx.transaction.as_ref().map(|tx| (tx, db_tx.sent))))
    -            // recalcuate sent value, only update txs in which sent value is changed
    -            .filter_map(|(raw_tx, old_sent)| {
    -                self.sent_from_raw_tx(raw_tx)
    -                    .map(|sent| {
    -                        if sent != old_sent {
    -                            Some((raw_tx.txid(), sent))
    -                        } else {
    -                            None
    -                        }
    -                    })
    -                    .transpose()
    -            })
    -            .collect::<Result<Vec<_>, _>>()?;
    -
    -        // record send updates
    -        sent_updates.iter().for_each(|&(txid, sent)| {
    -            // apply sent field changes
    -            self.txs.entry(txid).and_modify(|db_tx| db_tx.sent = sent);
    -            // mark tx as modified
    -            self.updated_txs.insert(txid);
    -        });
    -
    -        // obtain UTXOs from Core wallet
    -        let core_utxos = client
    -            .list_unspent(Some(0), None, None, Some(true), None)?
    -            .into_iter()
    -            .filter_map(|utxo_entry| {
    -                let path_result = self
    -                    .db
    -                    .get_path_from_script_pubkey(&utxo_entry.script_pub_key)
    -                    .transpose()?;
    -
    -                let utxo_result = match path_result {
    -                    Ok((keychain, index)) => {
    -                        self.update_last_index(keychain, index);
    -                        Ok(Self::make_local_utxo(utxo_entry, keychain, false))
    -                    }
    -                    Err(err) => Err(err),
    -                };
    -
    -                Some(utxo_result)
    -            })
    -            .collect::<Result<HashSet<_>, Error>>()?;
    -
    -        // mark "spent utxos" to be updated in database
    -        let spent_utxos = self.utxos.difference(&core_utxos).cloned().map(|mut utxo| {
    -            utxo.is_spent = true;
    -            utxo
    -        });
    -
    -        // mark new utxos to be added in database
    -        let new_utxos = core_utxos.difference(&self.utxos).cloned();
    -
    -        // add to updated utxos
    -        self.updated_utxos.extend(spent_utxos.chain(new_utxos));
    -
    -        Ok(self)
    -    }
    -
    -    /// Calculates received amount from raw tx.
    -    fn received_from_raw_tx(db: &D, raw_tx: &Transaction) -> Result<u64, Error> {
    -        raw_tx.output.iter().try_fold(0_u64, |recv, txo| {
    -            let v = if db.is_mine(&txo.script_pubkey)? {
    -                txo.value
    -            } else {
    -                0
    -            };
    -            Ok(recv + v)
    -        })
    -    }
    -
    -    /// Calculates sent from raw tx.
    -    fn sent_from_raw_tx(&self, raw_tx: &Transaction) -> Result<u64, Error> {
    -        let get_output = |outpoint: &OutPoint| {
    -            let raw_tx = self.txs.get(&outpoint.txid)?.transaction.as_ref()?;
    -            raw_tx.output.get(outpoint.vout as usize)
    -        };
    -
    -        raw_tx.input.iter().try_fold(0_u64, |sent, txin| {
    -            let v = match get_output(&txin.previous_output) {
    -                Some(prev_txo) => {
    -                    if self.db.is_mine(&prev_txo.script_pubkey)? {
    -                        prev_txo.value
    -                    } else {
    -                        0
    -                    }
    -                }
    -                None => 0_u64,
    -            };
    -            Ok(sent + v)
    -        })
    -    }
    -
    -    // updates the db state's last_index for the given keychain (if larger than current last_index)
    -    fn update_last_index(&mut self, keychain: KeychainKind, index: u32) {
    -        self.last_indexes
    -            .entry(keychain)
    -            .and_modify(|last| {
    -                if *last < index {
    -                    *last = index;
    -                }
    -            })
    -            .or_insert_with(|| index);
    -    }
    -
    -    fn make_local_utxo(
    -        entry: ListUnspentResultEntry,
    -        keychain: KeychainKind,
    -        is_spent: bool,
    -    ) -> LocalUtxo {
    -        LocalUtxo {
    -            outpoint: OutPoint::new(entry.txid, entry.vout),
    -            txout: TxOut {
    -                value: entry.amount.to_sat(),
    -                script_pubkey: entry.script_pub_key,
    -            },
    -            keychain,
    -            is_spent,
    -        }
    -    }
    -
    -    /// Prepare db batch operations.
    -    fn as_db_batch(&self) -> Result<D::Batch, Error> {
    -        let mut batch = self.db.begin_batch();
    -        let mut del_txs = 0_u32;
    -
    -        // delete stale (not retained) txs from db
    -        self.txs
    -            .keys()
    -            .filter(|&txid| !self.retained_txs.contains(txid))
    -            .try_for_each(|txid| -> Result<(), Error> {
    -                batch.del_tx(txid, false)?;
    -                del_txs += 1;
    -                Ok(())
    -            })?;
    -
    -        // update txs
    -        self.updated_txs
    -            .iter()
    -            .inspect(|&txid| debug!("updating tx: {}", txid))
    -            .try_for_each(|txid| batch.set_tx(self.txs.get(txid).unwrap()))?;
    -
    -        // update utxos
    -        self.updated_utxos
    -            .iter()
    -            .inspect(|&utxo| debug!("updating utxo: {}", utxo.outpoint))
    -            .try_for_each(|utxo| batch.set_utxo(utxo))?;
    -
    -        // update last indexes
    -        self.last_indexes
    -            .iter()
    -            .try_for_each(|(&keychain, &index)| batch.set_last_index(keychain, index))?;
    -
    -        info!(
    -            "db batch updates: del_txs={}, update_txs={}, update_utxos={}",
    -            del_txs,
    -            self.updated_txs.len(),
    -            self.updated_utxos.len()
    -        );
    -
    -        Ok(batch)
    -    }
    -}
    -
    -fn import_descriptors<'a, S>(
    -    client: &Client,
    -    start_epoch: u64,
    -    scripts_iter: S,
    -) -> Result<(), Error>
    -where
    -    S: Iterator<Item = &'a Script>,
    -{
    -    let requests = Value::Array(
    -        scripts_iter
    -            .map(|script| {
    -                let desc = descriptor_from_script_pubkey(script);
    -                json!({ "timestamp": start_epoch, "desc": desc })
    -            })
    -            .collect(),
    -    );
    -    for v in client.call::<Vec<Value>>("importdescriptors", &[requests])? {
    -        match v["success"].as_bool() {
    -            Some(true) => continue,
    -            Some(false) => {
    -                return Err(Error::Generic(
    -                    v["error"]["message"]
    -                        .as_str()
    -                        .map_or("unknown error".into(), ToString::to_string),
    -                ))
    -            }
    -            _ => return Err(Error::Generic("Unexpected response form Core".to_string())),
    -        }
    -    }
    -    Ok(())
    -}
    -
    -fn import_multi<'a, S>(client: &Client, start_epoch: u64, scripts_iter: S) -> Result<(), Error>
    -where
    -    S: Iterator<Item = &'a Script>,
    -{
    -    let requests = scripts_iter
    -        .map(|script| ImportMultiRequest {
    -            timestamp: ImportMultiRescanSince::Timestamp(start_epoch),
    -            script_pubkey: Some(ImportMultiRequestScriptPubkey::Script(script)),
    -            watchonly: Some(true),
    -            ..Default::default()
    -        })
    -        .collect::<Vec<_>>();
    -    let options = ImportMultiOptions { rescan: Some(true) };
    -    for v in client.import_multi(&requests, Some(&options))? {
    -        if let Some(err) = v.error {
    -            return Err(Error::Generic(format!(
    -                "{} (code: {})",
    -                err.message, err.code
    -            )));
    -        }
    -    }
    -    Ok(())
    -}
    -
    -/// Calls the `listtransactions` RPC method in `page_size`s and returns iterator of the tx results
    -/// in chronological order.
    -///
    -/// `page_size` cannot be less than 1 and cannot be greater than 1000.
    -fn list_transactions(
    -    client: &Client,
    -    page_size: usize,
    -) -> Result<impl Iterator<Item = ListTransactionResult>, Error> {
    -    if !(1..=1000).contains(&page_size) {
    -        return Err(Error::Generic(format!(
    -            "Core RPC method `listtransactions` must have `page_size` in range [1 to 1000]: got {}",
    -            page_size
    -        )));
    -    }
    -
    -    // `.take_while` helper to obtain the first error (TODO: remove when we can use `.map_while`)
    -    let mut got_err = false;
    -
    -    // obtain results in batches (of `page_size`)
    -    let nested_list = (0_usize..)
    -        .map(|page_index| {
    -            client.list_transactions(
    -                None,
    -                Some(page_size),
    -                Some(page_size * page_index),
    -                Some(true),
    -            )
    -        })
    -        // take until returned rpc call is empty or until error
    -        // TODO: replace with the following when MSRV is 1.57.0:
    -        // `.map_while(|res| res.map(|l| if l.is_empty() { None } else { Some(l) }).transpose())`
    -        .take_while(|res| {
    -            if got_err || matches!(res, Ok(list) if list.is_empty()) {
    -                // break if last iteration was an error, or if the current result is empty
    -                false
    -            } else {
    -                // record whether result is error or not
    -                got_err = res.is_err();
    -                // continue on non-empty result or first error
    -                true
    -            }
    -        })
    -        .collect::<Result<Vec<_>, _>>()
    -        .map_err(Error::Rpc)?;
    -
    -    // reverse here to have txs in chronological order
    -    Ok(nested_list.into_iter().rev().flatten())
    -}
    -
    -fn await_wallet_scan(client: &Client, rate_sec: u64, progress: &dyn Progress) -> Result<(), Error> {
    -    #[derive(Deserialize)]
    -    struct CallResult {
    -        scanning: ScanningDetails,
    -    }
    -
    -    let dur = Duration::from_secs(rate_sec);
    -    loop {
    -        match client.call::<CallResult>("getwalletinfo", &[])?.scanning {
    -            ScanningDetails::Scanning {
    -                duration,
    -                progress: pc,
    -            } => {
    -                debug!("scanning: duration={}, progress={}", duration, pc);
    -                progress.update(pc, Some(format!("elapsed for {} seconds", duration)))?;
    -                thread::sleep(dur);
    -            }
    -            ScanningDetails::NotScanning(_) => {
    -                progress.update(1.0, None)?;
    -                info!("scanning: done!");
    -                return Ok(());
    -            }
    -        };
    -    }
    -}
    -
    -/// Returns whether a wallet is legacy or descriptors by calling `getwalletinfo`.
    -///
    -/// This API is mapped by bitcoincore_rpc, but it doesn't have the fields we need (either
    -/// "descriptors" or "format") so we have to call the RPC manually
    -fn is_wallet_descriptor(client: &Client) -> Result<bool, Error> {
    -    #[derive(Deserialize)]
    -    struct CallResult {
    -        descriptors: Option<bool>,
    -    }
    -
    -    let result: CallResult = client.call("getwalletinfo", &[])?;
    -    Ok(result.descriptors.unwrap_or(false))
    -}
    -
    -fn descriptor_from_script_pubkey(script: &Script) -> String {
    -    let desc = format!("raw({})", script.to_hex());
    -    format!("{}#{}", desc, calc_checksum(&desc).unwrap())
    -}
    -
    -/// Factory of [`RpcBlockchain`] instances, implements [`BlockchainFactory`]
    -///
    -/// Internally caches the node url and authentication params and allows getting many different [`RpcBlockchain`]
    -/// objects for different wallet names and with different rescan heights.
    -///
    -/// ## Example
    -///
    -/// ```no_run
    -/// # use bdk::bitcoin::Network;
    -/// # use bdk::blockchain::BlockchainFactory;
    -/// # use bdk::blockchain::rpc::{Auth, RpcBlockchainFactory};
    -/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    -/// let factory = RpcBlockchainFactory {
    -///     url: "http://127.0.0.1:18332".to_string(),
    -///     auth: Auth::Cookie {
    -///         file: "/home/user/.bitcoin/.cookie".into(),
    -///     },
    -///     network: Network::Testnet,
    -///     wallet_name_prefix: Some("prefix-".to_string()),
    -///     default_skip_blocks: 100_000,
    -///     sync_params: None,
    -/// };
    -/// let main_wallet_blockchain = factory.build("main_wallet", Some(200_000))?;
    -/// # Ok(())
    -/// # }
    -/// ```
    -#[derive(Debug, Clone)]
    -pub struct RpcBlockchainFactory {
    -    /// The bitcoin node url
    -    pub url: String,
    -    /// The bitcoin node authentication mechanism
    -    pub auth: Auth,
    -    /// The network we are using (it will be checked the bitcoin node network matches this)
    -    pub network: Network,
    -    /// The optional prefix used to build the full wallet name for blockchains
    -    pub wallet_name_prefix: Option<String>,
    -    /// Default number of blocks to skip which will be inherited by blockchain unless overridden
    -    pub default_skip_blocks: u32,
    -    /// Sync parameters
    -    pub sync_params: Option<RpcSyncParams>,
    -}
    -
    -impl BlockchainFactory for RpcBlockchainFactory {
    -    type Inner = RpcBlockchain;
    -
    -    fn build(
    -        &self,
    -        checksum: &str,
    -        _override_skip_blocks: Option<u32>,
    -    ) -> Result<Self::Inner, Error> {
    -        RpcBlockchain::from_config(&RpcConfig {
    -            url: self.url.clone(),
    -            auth: self.auth.clone(),
    -            network: self.network,
    -            wallet_name: format!(
    -                "{}{}",
    -                self.wallet_name_prefix.as_ref().unwrap_or(&String::new()),
    -                checksum
    -            ),
    -            sync_params: self.sync_params.clone(),
    -        })
    -    }
    -}
    -
    -#[cfg(test)]
    -#[cfg(any(feature = "test-rpc", feature = "test-rpc-legacy"))]
    -mod test {
    -    use super::*;
    -    use crate::{
    -        descriptor::into_wallet_descriptor_checked, testutils::blockchain_tests::TestClient,
    -        wallet::utils::SecpCtx,
    -    };
    -
    -    use bitcoin::{Address, Network};
    -    use bitcoincore_rpc::RpcApi;
    -    use log::LevelFilter;
    -
    -    crate::bdk_blockchain_tests! {
    -        fn test_instance(test_client: &TestClient) -> RpcBlockchain {
    -            let config = RpcConfig {
    -                url: test_client.bitcoind.rpc_url(),
    -                auth: Auth::Cookie { file: test_client.bitcoind.params.cookie_file.clone() },
    -                network: Network::Regtest,
    -                wallet_name: format!("client-wallet-test-{}", std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos() ),
    -                sync_params: None,
    -            };
    -            RpcBlockchain::from_config(&config).unwrap()
    -        }
    -    }
    -
    -    fn get_factory() -> (TestClient, RpcBlockchainFactory) {
    -        let test_client = TestClient::default();
    -
    -        let factory = RpcBlockchainFactory {
    -            url: test_client.bitcoind.rpc_url(),
    -            auth: Auth::Cookie {
    -                file: test_client.bitcoind.params.cookie_file.clone(),
    -            },
    -            network: Network::Regtest,
    -            wallet_name_prefix: Some("prefix-".into()),
    -            default_skip_blocks: 0,
    -            sync_params: None,
    -        };
    -
    -        (test_client, factory)
    -    }
    -
    -    #[test]
    -    fn test_rpc_blockchain_factory() {
    -        let (_test_client, factory) = get_factory();
    -
    -        let a = factory.build("aaaaaa", None).unwrap();
    -        assert_eq!(
    -            a.client
    -                .get_wallet_info()
    -                .expect("Node connection isn't working")
    -                .wallet_name,
    -            "prefix-aaaaaa"
    -        );
    -
    -        let b = factory.build("bbbbbb", Some(100)).unwrap();
    -        assert_eq!(
    -            b.client
    -                .get_wallet_info()
    -                .expect("Node connection isn't working")
    -                .wallet_name,
    -            "prefix-bbbbbb"
    -        );
    -    }
    -
    -    /// This test ensures that [list_transactions] always iterates through transactions in
    -    /// chronological order, independent of the `page_size`.
    -    #[test]
    -    fn test_list_transactions() {
    -        let _ = env_logger::builder()
    -            .filter_level(LevelFilter::Info)
    -            .default_format()
    -            .try_init();
    -
    -        const DESC: &'static str = "wpkh(tpubD9zMNV59kgbWgKK55SHJugmKKSt6wQXczxpucGYqNKwGmJp1x7Ar2nrLUXYHDdCctXmyDoSCn2JVMzMUDfib3FaDhwxCEMUELoq19xLSx66/*)";
    -        const AMOUNT_PER_TX: u64 = 10_000;
    -        const TX_COUNT: u32 = 50;
    -
    -        let secp = SecpCtx::default();
    -        let network = Network::Regtest;
    -        let (desc, ..) = into_wallet_descriptor_checked(DESC, &secp, network).unwrap();
    -
    -        let (mut test_client, factory) = get_factory();
    -        let bc = factory.build("itertest", None).unwrap();
    -
    -        // generate scripts (1 tx per script)
    -        let scripts = (0..TX_COUNT)
    -            .map(|index| desc.at_derivation_index(index).script_pubkey())
    -            .collect::<Vec<_>>();
    -
    -        // import scripts and wait
    -        if bc.is_descriptors {
    -            import_descriptors(&bc.client, 0, scripts.iter()).unwrap();
    -        } else {
    -            import_multi(&bc.client, 0, scripts.iter()).unwrap();
    -        }
    -        await_wallet_scan(&bc.client, 2, &NoopProgress).unwrap();
    -
    -        // create and broadcast txs
    -        let expected_txids = scripts
    -            .iter()
    -            .map(|script| {
    -                let addr = Address::from_script(script, network).unwrap();
    -                let txid =
    -                    test_client.receive(testutils! { @tx ( (@addr addr) => AMOUNT_PER_TX ) });
    -                test_client.generate(1, None);
    -                txid
    -            })
    -            .collect::<Vec<_>>();
    -
    -        // iterate through different page sizes - should always return txs in chronological order
    -        [1000, 1, 2, 6, 25, 49, 50].iter().for_each(|page_size| {
    -            println!("trying with page_size: {}", page_size);
    -
    -            let txids = list_transactions(&bc.client, *page_size)
    -                .unwrap()
    -                .map(|res| res.info.txid)
    -                .collect::<Vec<_>>();
    -
    -            assert_eq!(txids.len(), expected_txids.len());
    -            assert_eq!(txids, expected_txids);
    -        });
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/script_sync.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/script_sync.rs.html deleted file mode 100644 index 8469092fbb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/script_sync.rs.html +++ /dev/null @@ -1,937 +0,0 @@ -script_sync.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -
    /*!
    -This models a how a sync happens where you have a server that you send your script pubkeys to and it
    -returns associated transactions i.e. electrum.
    -*/
    -#![allow(dead_code)]
    -use crate::{
    -    database::{BatchDatabase, BatchOperations, DatabaseUtils},
    -    error::MissingCachedScripts,
    -    wallet::time::Instant,
    -    BlockTime, Error, KeychainKind, LocalUtxo, TransactionDetails,
    -};
    -use bitcoin::{OutPoint, Script, Transaction, TxOut, Txid};
    -use log::*;
    -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
    -
    -/// A request for on-chain information
    -pub enum Request<'a, D: BatchDatabase> {
    -    /// A request for transactions related to script pubkeys.
    -    Script(ScriptReq<'a, D>),
    -    /// A request for confirmation times for some transactions.
    -    Conftime(ConftimeReq<'a, D>),
    -    /// A request for full transaction details of some transactions.
    -    Tx(TxReq<'a, D>),
    -    /// Requests are finished here's a batch database update to reflect data gathered.
    -    Finish(D::Batch),
    -}
    -
    -/// starts a sync
    -pub fn start<D: BatchDatabase>(db: &D, stop_gap: usize) -> Result<Request<'_, D>, Error> {
    -    use rand::seq::SliceRandom;
    -    let mut keychains = vec![KeychainKind::Internal, KeychainKind::External];
    -    // shuffling improve privacy, the server doesn't know my first request is from my internal or external addresses
    -    keychains.shuffle(&mut rand::thread_rng());
    -    let keychain = keychains.pop().unwrap();
    -    let scripts_needed = db
    -        .iter_script_pubkeys(Some(keychain))?
    -        .into_iter()
    -        .collect::<VecDeque<_>>();
    -    let state = State::new(db);
    -
    -    Ok(Request::Script(ScriptReq {
    -        state,
    -        initial_scripts_needed: scripts_needed.len(),
    -        scripts_needed,
    -        script_index: 0,
    -        stop_gap,
    -        keychain,
    -        next_keychains: keychains,
    -    }))
    -}
    -
    -pub struct ScriptReq<'a, D: BatchDatabase> {
    -    state: State<'a, D>,
    -    script_index: usize,
    -    initial_scripts_needed: usize, // if this is 1, we assume the descriptor is not derivable
    -    scripts_needed: VecDeque<Script>,
    -    stop_gap: usize,
    -    keychain: KeychainKind,
    -    next_keychains: Vec<KeychainKind>,
    -}
    -
    -/// The sync starts by returning script pubkeys we are interested in.
    -impl<'a, D: BatchDatabase> ScriptReq<'a, D> {
    -    pub fn request(&self) -> impl Iterator<Item = &Script> + Clone {
    -        self.scripts_needed.iter()
    -    }
    -
    -    pub fn satisfy(
    -        mut self,
    -        // we want to know the txids assoiciated with the script and their height
    -        txids: Vec<Vec<(Txid, Option<u32>)>>,
    -    ) -> Result<Request<'a, D>, Error> {
    -        for (txid_list, script) in txids.iter().zip(self.scripts_needed.iter()) {
    -            debug!(
    -                "found {} transactions for script pubkey {}",
    -                txid_list.len(),
    -                script
    -            );
    -            if !txid_list.is_empty() {
    -                // the address is active
    -                self.state
    -                    .last_active_index
    -                    .insert(self.keychain, self.script_index);
    -            }
    -
    -            for (txid, height) in txid_list {
    -                // have we seen this txid already?
    -                match self.state.db.get_tx(txid, true)? {
    -                    Some(mut details) => {
    -                        let old_height = details.confirmation_time.as_ref().map(|x| x.height);
    -                        match (old_height, height) {
    -                            (None, Some(_)) => {
    -                                // It looks like the tx has confirmed since we last saw it -- we
    -                                // need to know the confirmation time.
    -                                self.state.tx_missing_conftime.insert(*txid, details);
    -                            }
    -                            (Some(old_height), Some(new_height)) if old_height != *new_height => {
    -                                // The height of the tx has changed !? -- It's a reorg get the new confirmation time.
    -                                self.state.tx_missing_conftime.insert(*txid, details);
    -                            }
    -                            (Some(_), None) => {
    -                                // A re-org where the tx is not in the chain anymore.
    -                                details.confirmation_time = None;
    -                                self.state.finished_txs.push(details);
    -                            }
    -                            _ => self.state.finished_txs.push(details),
    -                        }
    -                    }
    -                    None => {
    -                        // we've never seen it let's get the whole thing
    -                        self.state.tx_needed.insert(*txid);
    -                    }
    -                };
    -            }
    -
    -            self.script_index += 1;
    -        }
    -
    -        self.scripts_needed.drain(..txids.len());
    -
    -        // last active index: 0 => No last active
    -        let last = self
    -            .state
    -            .last_active_index
    -            .get(&self.keychain)
    -            .map(|&l| l + 1)
    -            .unwrap_or(0);
    -        // remaining scripts left to check
    -        let remaining = self.scripts_needed.len();
    -        // difference between current index and last active index
    -        let current_gap = self.script_index - last;
    -
    -        // this is a hack to check whether the scripts are coming from a derivable descriptor
    -        // we assume for non-derivable descriptors, the initial script count is always 1
    -        let is_derivable = self.initial_scripts_needed > 1;
    -
    -        debug!(
    -            "sync: last={}, remaining={}, diff={}, stop_gap={}",
    -            last, remaining, current_gap, self.stop_gap
    -        );
    -
    -        if is_derivable {
    -            if remaining > 0 {
    -                // we still have scriptPubKeys to do requests for
    -                return Ok(Request::Script(self));
    -            }
    -
    -            if last > 0 && current_gap < self.stop_gap {
    -                // current gap is not large enough to stop, but we are unable to keep checking since
    -                // we have exhausted cached scriptPubKeys, so return error
    -                let err = MissingCachedScripts {
    -                    last_count: self.script_index,
    -                    missing_count: self.stop_gap - current_gap,
    -                };
    -                return Err(Error::MissingCachedScripts(err));
    -            }
    -
    -            // we have exhausted cached scriptPubKeys and found no txs, continue
    -        }
    -
    -        debug!(
    -            "finished scanning for txs of keychain {:?} at index {:?}",
    -            self.keychain, last
    -        );
    -
    -        if let Some(keychain) = self.next_keychains.pop() {
    -            // we still have another keychain to request txs with
    -            let scripts_needed = self
    -                .state
    -                .db
    -                .iter_script_pubkeys(Some(keychain))?
    -                .into_iter()
    -                .collect::<VecDeque<_>>();
    -
    -            self.keychain = keychain;
    -            self.script_index = 0;
    -            self.initial_scripts_needed = scripts_needed.len();
    -            self.scripts_needed = scripts_needed;
    -            return Ok(Request::Script(self));
    -        }
    -
    -        // We have finished requesting txids, let's get the actual txs.
    -        Ok(Request::Tx(TxReq { state: self.state }))
    -    }
    -}
    -
    -/// Then we get full transactions
    -pub struct TxReq<'a, D> {
    -    state: State<'a, D>,
    -}
    -
    -impl<'a, D: BatchDatabase> TxReq<'a, D> {
    -    pub fn request(&self) -> impl Iterator<Item = &Txid> + Clone {
    -        self.state.tx_needed.iter()
    -    }
    -
    -    pub fn satisfy(
    -        mut self,
    -        tx_details: Vec<(Vec<Option<TxOut>>, Transaction)>,
    -    ) -> Result<Request<'a, D>, Error> {
    -        let tx_details: Vec<TransactionDetails> = tx_details
    -            .into_iter()
    -            .zip(self.state.tx_needed.iter())
    -            .map(|((vout, tx), txid)| {
    -                debug!("found tx_details for {}", txid);
    -                assert_eq!(tx.txid(), *txid);
    -                let mut sent: u64 = 0;
    -                let mut received: u64 = 0;
    -                let mut inputs_sum: u64 = 0;
    -                let mut outputs_sum: u64 = 0;
    -
    -                for (txout, (_input_index, input)) in
    -                    vout.into_iter().zip(tx.input.iter().enumerate())
    -                {
    -                    let txout = match txout {
    -                        Some(txout) => txout,
    -                        None => {
    -                            // skip coinbase inputs
    -                            debug_assert!(
    -                                input.previous_output.is_null(),
    -                                "prevout should only be missing for coinbase"
    -                            );
    -                            continue;
    -                        }
    -                    };
    -                    // Verify this input if requested via feature flag
    -                    #[cfg(feature = "verify")]
    -                    {
    -                        use crate::wallet::verify::VerifyError;
    -                        let serialized_tx = bitcoin::consensus::serialize(&tx);
    -                        bitcoinconsensus::verify(
    -                            txout.script_pubkey.to_bytes().as_ref(),
    -                            txout.value,
    -                            &serialized_tx,
    -                            _input_index,
    -                        )
    -                        .map_err(VerifyError::from)?;
    -                    }
    -                    inputs_sum += txout.value;
    -                    if self.state.db.is_mine(&txout.script_pubkey)? {
    -                        sent += txout.value;
    -                    }
    -                }
    -
    -                for out in &tx.output {
    -                    outputs_sum += out.value;
    -                    if self.state.db.is_mine(&out.script_pubkey)? {
    -                        received += out.value;
    -                    }
    -                }
    -                // we need to saturating sub since we want coinbase txs to map to 0 fee and
    -                // this subtraction will be negative for coinbase txs.
    -                let fee = inputs_sum.saturating_sub(outputs_sum);
    -                Result::<_, Error>::Ok(TransactionDetails {
    -                    txid: *txid,
    -                    transaction: Some(tx),
    -                    received,
    -                    sent,
    -                    // we're going to fill this in later
    -                    confirmation_time: None,
    -                    fee: Some(fee),
    -                })
    -            })
    -            .collect::<Result<Vec<_>, _>>()?;
    -
    -        for tx_detail in tx_details {
    -            self.state.tx_needed.remove(&tx_detail.txid);
    -            self.state
    -                .tx_missing_conftime
    -                .insert(tx_detail.txid, tx_detail);
    -        }
    -
    -        if !self.state.tx_needed.is_empty() {
    -            Ok(Request::Tx(self))
    -        } else {
    -            Ok(Request::Conftime(ConftimeReq { state: self.state }))
    -        }
    -    }
    -}
    -
    -/// Final step is to get confirmation times
    -pub struct ConftimeReq<'a, D> {
    -    state: State<'a, D>,
    -}
    -
    -impl<'a, D: BatchDatabase> ConftimeReq<'a, D> {
    -    pub fn request(&self) -> impl Iterator<Item = &Txid> + Clone {
    -        self.state.tx_missing_conftime.keys()
    -    }
    -
    -    pub fn satisfy(
    -        mut self,
    -        confirmation_times: Vec<Option<BlockTime>>,
    -    ) -> Result<Request<'a, D>, Error> {
    -        let conftime_needed = self
    -            .request()
    -            .cloned()
    -            .take(confirmation_times.len())
    -            .collect::<Vec<_>>();
    -        for (confirmation_time, txid) in confirmation_times.into_iter().zip(conftime_needed.iter())
    -        {
    -            debug!("confirmation time for {} was {:?}", txid, confirmation_time);
    -            if let Some(mut tx_details) = self.state.tx_missing_conftime.remove(txid) {
    -                tx_details.confirmation_time = confirmation_time;
    -                self.state.finished_txs.push(tx_details);
    -            }
    -        }
    -
    -        if self.state.tx_missing_conftime.is_empty() {
    -            Ok(Request::Finish(self.state.into_db_update()?))
    -        } else {
    -            Ok(Request::Conftime(self))
    -        }
    -    }
    -}
    -
    -struct State<'a, D> {
    -    db: &'a D,
    -    last_active_index: HashMap<KeychainKind, usize>,
    -    /// Transactions where we need to get the full details
    -    tx_needed: BTreeSet<Txid>,
    -    /// Transacitions that we know everything about
    -    finished_txs: Vec<TransactionDetails>,
    -    /// Transactions that discovered conftimes should be inserted into
    -    tx_missing_conftime: BTreeMap<Txid, TransactionDetails>,
    -    /// The start of the sync
    -    start_time: Instant,
    -    /// Missing number of scripts to cache per keychain
    -    missing_script_counts: HashMap<KeychainKind, usize>,
    -}
    -
    -impl<'a, D: BatchDatabase> State<'a, D> {
    -    fn new(db: &'a D) -> Self {
    -        State {
    -            db,
    -            last_active_index: HashMap::default(),
    -            finished_txs: vec![],
    -            tx_needed: BTreeSet::default(),
    -            tx_missing_conftime: BTreeMap::default(),
    -            start_time: Instant::new(),
    -            missing_script_counts: HashMap::default(),
    -        }
    -    }
    -    fn into_db_update(self) -> Result<D::Batch, Error> {
    -        debug_assert!(self.tx_needed.is_empty() && self.tx_missing_conftime.is_empty());
    -        let existing_txs = self.db.iter_txs(false)?;
    -        let existing_txids: HashSet<Txid> = existing_txs.iter().map(|tx| tx.txid).collect();
    -        let finished_txs = make_txs_consistent(&self.finished_txs);
    -        let observed_txids: HashSet<Txid> = finished_txs.iter().map(|tx| tx.txid).collect();
    -        let txids_to_delete = existing_txids.difference(&observed_txids);
    -
    -        // Ensure `last_active_index` does not decrement database's current state.
    -        let index_updates = self
    -            .last_active_index
    -            .iter()
    -            .map(|(keychain, sync_index)| {
    -                let sync_index = *sync_index as u32;
    -                let index_res = match self.db.get_last_index(*keychain) {
    -                    Ok(Some(db_index)) => Ok(std::cmp::max(db_index, sync_index)),
    -                    Ok(None) => Ok(sync_index),
    -                    Err(err) => Err(err),
    -                };
    -                index_res.map(|index| (*keychain, index))
    -            })
    -            .collect::<Result<Vec<(KeychainKind, u32)>, _>>()?;
    -
    -        let mut batch = self.db.begin_batch();
    -
    -        // Delete old txs that no longer exist
    -        for txid in txids_to_delete {
    -            if let Some(raw_tx) = self.db.get_raw_tx(txid)? {
    -                for i in 0..raw_tx.output.len() {
    -                    // Also delete any utxos from the txs that no longer exist.
    -                    let _ = batch.del_utxo(&OutPoint {
    -                        txid: *txid,
    -                        vout: i as u32,
    -                    })?;
    -                }
    -            } else {
    -                unreachable!("we should always have the raw tx");
    -            }
    -            batch.del_tx(txid, true)?;
    -        }
    -
    -        let mut spent_utxos = HashSet::new();
    -
    -        // track all the spent utxos
    -        for finished_tx in &finished_txs {
    -            let tx = finished_tx
    -                .transaction
    -                .as_ref()
    -                .expect("transaction will always be present here");
    -            for input in &tx.input {
    -                spent_utxos.insert(&input.previous_output);
    -            }
    -        }
    -
    -        // set every utxo we observed, unless it's already spent
    -        // we don't do this in the loop above as we want to know all the spent outputs before
    -        // adding the non-spent to the batch in case there are new tranasactions
    -        // that spend form each other.
    -        for finished_tx in &finished_txs {
    -            let tx = finished_tx
    -                .transaction
    -                .as_ref()
    -                .expect("transaction will always be present here");
    -            for (i, output) in tx.output.iter().enumerate() {
    -                if let Some((keychain, _)) =
    -                    self.db.get_path_from_script_pubkey(&output.script_pubkey)?
    -                {
    -                    // add utxos we own from the new transactions we've seen.
    -                    let outpoint = OutPoint {
    -                        txid: finished_tx.txid,
    -                        vout: i as u32,
    -                    };
    -
    -                    batch.set_utxo(&LocalUtxo {
    -                        outpoint,
    -                        txout: output.clone(),
    -                        keychain,
    -                        // Is this UTXO in the spent_utxos set?
    -                        is_spent: spent_utxos.get(&outpoint).is_some(),
    -                    })?;
    -                }
    -            }
    -
    -            batch.set_tx(finished_tx)?;
    -        }
    -
    -        // apply index updates
    -        for (keychain, new_index) in index_updates {
    -            debug!("updating index ({}, {})", keychain.as_byte(), new_index);
    -            batch.set_last_index(keychain, new_index)?;
    -        }
    -
    -        info!(
    -            "finished setup, elapsed {:?}ms",
    -            self.start_time.elapsed().as_millis()
    -        );
    -        Ok(batch)
    -    }
    -}
    -
    -/// Remove conflicting transactions -- tie breaking them by fee.
    -fn make_txs_consistent(txs: &[TransactionDetails]) -> Vec<&TransactionDetails> {
    -    let mut utxo_index: HashMap<OutPoint, &TransactionDetails> = HashMap::default();
    -    for tx in txs {
    -        for input in &tx.transaction.as_ref().unwrap().input {
    -            utxo_index
    -                .entry(input.previous_output)
    -                .and_modify(|existing| match (tx.fee, existing.fee) {
    -                    (Some(fee), Some(existing_fee)) if fee > existing_fee => *existing = tx,
    -                    (Some(_), None) => *existing = tx,
    -                    _ => { /* leave it the same */ }
    -                })
    -                .or_insert(tx);
    -        }
    -    }
    -
    -    utxo_index
    -        .into_iter()
    -        .map(|(_, tx)| (tx.txid, tx))
    -        .collect::<HashMap<_, _>>()
    -        .into_iter()
    -        .map(|(_, tx)| tx)
    -        .collect()
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html deleted file mode 100644 index 233a66debb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html +++ /dev/null @@ -1,857 +0,0 @@ -any.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Runtime-checked database types
    -//!
    -//! This module provides the implementation of [`AnyDatabase`] which allows switching the
    -//! inner [`Database`] type at runtime.
    -//!
    -//! ## Example
    -//!
    -//! In this example, `wallet_memory` and `wallet_sled` have the same type of `Wallet<(), AnyDatabase>`.
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::database::{AnyDatabase, MemoryDatabase};
    -//! # use bdk::{Wallet};
    -//! let memory = MemoryDatabase::default();
    -//! let wallet_memory = Wallet::new("...", None, Network::Testnet, memory)?;
    -//!
    -//! # #[cfg(feature = "key-value-db")]
    -//! # {
    -//! let sled = sled::open("my-database")?.open_tree("default_tree")?;
    -//! let wallet_sled = Wallet::new("...", None, Network::Testnet, sled)?;
    -//! # }
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -//!
    -//! When paired with the use of [`ConfigurableDatabase`], it allows creating wallets with any
    -//! database supported using a single line of code:
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::database::*;
    -//! # use bdk::{Wallet};
    -//! let config = serde_json::from_str("...")?;
    -//! let database = AnyDatabase::from_config(&config)?;
    -//! let wallet = Wallet::new("...", None, Network::Testnet, database)?;
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use super::*;
    -
    -macro_rules! impl_from {
    -    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
    -        $( $cfg )*
    -        impl From<$from> for $to {
    -            fn from(inner: $from) -> Self {
    -                <$to>::$variant(inner)
    -            }
    -        }
    -    };
    -}
    -
    -macro_rules! impl_inner_method {
    -    ( $enum_name:ident, $self:expr, $name:ident $(, $args:expr)* ) => {
    -        #[allow(deprecated)]
    -        match $self {
    -            $enum_name::Memory(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "key-value-db")]
    -            $enum_name::Sled(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "sqlite")]
    -            $enum_name::Sqlite(inner) => inner.$name( $($args, )* ),
    -        }
    -    }
    -}
    -
    -/// Type that can contain any of the [`Database`] types defined by the library
    -///
    -/// It allows switching database type at runtime.
    -///
    -/// See [this module](crate::database::any)'s documentation for a usage example.
    -#[derive(Debug)]
    -pub enum AnyDatabase {
    -    /// In-memory ephemeral database
    -    Memory(memory::MemoryDatabase),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(sled::Tree),
    -    #[cfg(feature = "sqlite")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
    -    /// Sqlite embedded database using [`rusqlite`]
    -    Sqlite(sqlite::SqliteDatabase),
    -}
    -
    -impl_from!(memory::MemoryDatabase, AnyDatabase, Memory,);
    -impl_from!(sled::Tree, AnyDatabase, Sled, #[cfg(feature = "key-value-db")]);
    -impl_from!(sqlite::SqliteDatabase, AnyDatabase, Sqlite, #[cfg(feature = "sqlite")]);
    -
    -/// Type that contains any of the [`BatchDatabase::Batch`] types defined by the library
    -pub enum AnyBatch {
    -    /// In-memory ephemeral database
    -    Memory(<memory::MemoryDatabase as BatchDatabase>::Batch),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(<sled::Tree as BatchDatabase>::Batch),
    -    #[cfg(feature = "sqlite")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
    -    /// Sqlite embedded database using [`rusqlite`]
    -    Sqlite(<sqlite::SqliteDatabase as BatchDatabase>::Batch),
    -}
    -
    -impl_from!(
    -    <memory::MemoryDatabase as BatchDatabase>::Batch,
    -    AnyBatch,
    -    Memory,
    -);
    -impl_from!(<sled::Tree as BatchDatabase>::Batch, AnyBatch, Sled, #[cfg(feature = "key-value-db")]);
    -impl_from!(<sqlite::SqliteDatabase as BatchDatabase>::Batch, AnyBatch, Sqlite, #[cfg(feature = "sqlite")]);
    -
    -impl BatchOperations for AnyDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            set_script_pubkey,
    -            script,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_utxo, utxo)
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_raw_tx, transaction)
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_tx, transaction)
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
    -    }
    -    fn set_sync_time(&mut self, sync_time: SyncTime) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_sync_time, sync_time)
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            del_script_pubkey_from_path,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_path_from_script_pubkey, script)
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_utxo, outpoint)
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_raw_tx, txid)
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_tx, txid, include_raw)
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
    -    }
    -    fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_sync_time)
    -    }
    -}
    -
    -impl Database for AnyDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            check_descriptor_checksum,
    -            keychain,
    -            bytes
    -        )
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_script_pubkeys, keychain)
    -    }
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_utxos)
    -    }
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_raw_txs)
    -    }
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_txs, include_raw)
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            get_script_pubkey_from_path,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_path_from_script_pubkey, script)
    -    }
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_utxo, outpoint)
    -    }
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_raw_tx, txid)
    -    }
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_tx, txid, include_raw)
    -    }
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
    -    }
    -    fn get_sync_time(&self) -> Result<Option<SyncTime>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_sync_time)
    -    }
    -
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
    -    }
    -}
    -
    -impl BatchOperations for AnyBatch {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_script_pubkey, script, keychain, child)
    -    }
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_utxo, utxo)
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_raw_tx, transaction)
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_tx, transaction)
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
    -    }
    -    fn set_sync_time(&mut self, sync_time: SyncTime) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_sync_time, sync_time)
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_script_pubkey_from_path, keychain, child)
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_path_from_script_pubkey, script)
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_utxo, outpoint)
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_raw_tx, txid)
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_tx, txid, include_raw)
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_last_index, keychain)
    -    }
    -    fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_sync_time)
    -    }
    -}
    -
    -impl BatchDatabase for AnyDatabase {
    -    type Batch = AnyBatch;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        match self {
    -            AnyDatabase::Memory(inner) => inner.begin_batch().into(),
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabase::Sled(inner) => inner.begin_batch().into(),
    -            #[cfg(feature = "sqlite")]
    -            AnyDatabase::Sqlite(inner) => inner.begin_batch().into(),
    -        }
    -    }
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        match self {
    -            AnyDatabase::Memory(db) => match batch {
    -                AnyBatch::Memory(batch) => db.commit_batch(batch),
    -                #[cfg(any(feature = "key-value-db", feature = "sqlite"))]
    -                _ => unimplemented!("Other batch shouldn't be used with Memory db."),
    -            },
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabase::Sled(db) => match batch {
    -                AnyBatch::Sled(batch) => db.commit_batch(batch),
    -                _ => unimplemented!("Other batch shouldn't be used with Sled db."),
    -            },
    -            #[cfg(feature = "sqlite")]
    -            AnyDatabase::Sqlite(db) => match batch {
    -                AnyBatch::Sqlite(batch) => db.commit_batch(batch),
    -                _ => unimplemented!("Other batch shouldn't be used with Sqlite db."),
    -            },
    -        }
    -    }
    -}
    -
    -/// Configuration type for a [`sled::Tree`] database
    -#[cfg(feature = "key-value-db")]
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub struct SledDbConfiguration {
    -    /// Main directory of the db
    -    pub path: String,
    -    /// Name of the database tree, a separated namespace for the data
    -    pub tree_name: String,
    -}
    -
    -#[cfg(feature = "key-value-db")]
    -impl ConfigurableDatabase for sled::Tree {
    -    type Config = SledDbConfiguration;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(sled::open(&config.path)?.open_tree(&config.tree_name)?)
    -    }
    -}
    -
    -/// Configuration type for a [`sqlite::SqliteDatabase`] database
    -#[cfg(feature = "sqlite")]
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub struct SqliteDbConfiguration {
    -    /// Main directory of the db
    -    pub path: String,
    -}
    -
    -#[cfg(feature = "sqlite")]
    -impl ConfigurableDatabase for sqlite::SqliteDatabase {
    -    type Config = SqliteDbConfiguration;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(sqlite::SqliteDatabase::new(config.path.clone()))
    -    }
    -}
    -
    -/// Type that can contain any of the database configurations defined by the library
    -///
    -/// This allows storing a single configuration that can be loaded into an [`AnyDatabase`]
    -/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
    -/// will find this particularly useful.
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub enum AnyDatabaseConfig {
    -    /// Memory database has no config
    -    Memory(()),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(SledDbConfiguration),
    -    #[cfg(feature = "sqlite")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
    -    /// Sqlite embedded database using [`rusqlite`]
    -    Sqlite(SqliteDbConfiguration),
    -}
    -
    -impl ConfigurableDatabase for AnyDatabase {
    -    type Config = AnyDatabaseConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(match config {
    -            AnyDatabaseConfig::Memory(inner) => {
    -                AnyDatabase::Memory(memory::MemoryDatabase::from_config(inner)?)
    -            }
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabaseConfig::Sled(inner) => AnyDatabase::Sled(sled::Tree::from_config(inner)?),
    -            #[cfg(feature = "sqlite")]
    -            AnyDatabaseConfig::Sqlite(inner) => {
    -                AnyDatabase::Sqlite(sqlite::SqliteDatabase::from_config(inner)?)
    -            }
    -        })
    -    }
    -}
    -
    -impl_from!((), AnyDatabaseConfig, Memory,);
    -impl_from!(SledDbConfiguration, AnyDatabaseConfig, Sled, #[cfg(feature = "key-value-db")]);
    -impl_from!(SqliteDbConfiguration, AnyDatabaseConfig, Sqlite, #[cfg(feature = "sqlite")]);
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html deleted file mode 100644 index 28ba9772bf..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html +++ /dev/null @@ -1,1073 +0,0 @@ -keyvalue.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::convert::TryInto;
    -
    -use sled::{Batch, Tree};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::memory::MapKey;
    -use crate::database::{BatchDatabase, BatchOperations, Database, SyncTime};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -macro_rules! impl_batch_operations {
    -    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
    -        fn set_script_pubkey(&mut self, script: &Script, keychain: KeychainKind, path: u32) -> Result<(), Error> {
    -            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -            self.insert(key, serialize(script))$($after_insert)*;
    -
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let value = json!({
    -                "t": keychain,
    -                "p": path,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -            let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
    -            let value = json!({
    -                "t": utxo.txout,
    -                "i": utxo.keychain,
    -                "s": utxo.is_spent,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -            let value = serialize(transaction);
    -            self.insert(key, value)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -            // remove the raw tx from the serialized version
    -            let mut value = serde_json::to_value(transaction)?;
    -            value["transaction"] = serde_json::Value::Null;
    -            let value = serde_json::to_vec(&value)?;
    -
    -            self.insert(key, value)$($after_insert)*;
    -
    -            // insert the raw_tx if present
    -            if let Some(ref tx) = transaction.transaction {
    -                self.set_raw_tx(tx)?;
    -            }
    -
    -            Ok(())
    -        }
    -
    -        fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -            let key = MapKey::LastIndex(keychain).as_map_key();
    -            self.insert(key, &value.to_be_bytes())$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_sync_time(&mut self, data: SyncTime) -> Result<(), Error> {
    -            let key = MapKey::SyncTime.as_map_key();
    -            self.insert(key, serde_json::to_vec(&data)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn del_script_pubkey_from_path(&mut self, keychain: KeychainKind, path: u32) -> Result<Option<Script>, Error> {
    -            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(KeychainKind, u32)>, Error> {
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let st = serde_json::from_value(val["t"].take())?;
    -                    let path = serde_json::from_value(val["p"].take())?;
    -
    -                    Ok(Some((st, path)))
    -                }
    -            }
    -        }
    -
    -        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -            let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let txout = serde_json::from_value(val["t"].take())?;
    -                    let keychain = serde_json::from_value(val["i"].take())?;
    -                    let is_spent = val.get_mut("s").and_then(|s| s.take().as_bool()).unwrap_or(false);
    -
    -                    Ok(Some(LocalUtxo { outpoint: outpoint.clone(), txout, keychain, is_spent, }))
    -                }
    -            }
    -        }
    -
    -        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -            let key = MapKey::RawTx(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -            let raw_tx = if include_raw {
    -                self.del_raw_tx(txid)?
    -            } else {
    -                None
    -            };
    -
    -            let key = MapKey::Transaction(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
    -                    val.transaction = raw_tx;
    -
    -                    Ok(Some(val))
    -                }
    -            }
    -        }
    -
    -        fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -            let key = MapKey::LastIndex(keychain).as_map_key();
    -            let res = self.remove(key);
    -            $process_delete!(res)
    -            .map(ivec_to_u32)
    -            .transpose()
    -        }
    -
    -        fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error> {
    -            let key = MapKey::SyncTime.as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map(|b| serde_json::from_slice(&b)).transpose()?)
    -        }
    -    }
    -}
    -
    -macro_rules! process_delete_tree {
    -    ($res:expr) => {
    -        $res?
    -    };
    -}
    -impl BatchOperations for Tree {
    -    impl_batch_operations!({?}, process_delete_tree);
    -}
    -
    -macro_rules! process_delete_batch {
    -    ($res:expr) => {
    -        None as Option<sled::IVec>
    -    };
    -}
    -#[allow(unused_variables)]
    -impl BatchOperations for Batch {
    -    impl_batch_operations!({}, process_delete_batch);
    -}
    -
    -impl Database for Tree {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
    -
    -        let prev = self.get(&key)?.map(|x| x.to_vec());
    -        if let Some(val) = prev {
    -            if val == bytes.as_ref() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.insert(&key, bytes.as_ref())?;
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((keychain, None)).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let outpoint = deserialize(&k[1..])?;
    -
    -                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let keychain = serde_json::from_value(val["i"].take())?;
    -                let is_spent = val
    -                    .get_mut("s")
    -                    .and_then(|s| s.take().as_bool())
    -                    .unwrap_or(false);
    -
    -                Ok(LocalUtxo {
    -                    outpoint,
    -                    txout,
    -                    keychain,
    -                    is_spent,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok((st, path))
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let keychain = serde_json::from_value(val["i"].take())?;
    -                let is_spent = val
    -                    .get_mut("s")
    -                    .and_then(|s| s.take().as_bool())
    -                    .unwrap_or(false);
    -
    -                Ok(LocalUtxo {
    -                    outpoint: *outpoint,
    -                    txout,
    -                    keychain,
    -                    is_spent,
    -                })
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
    -                if include_raw {
    -                    txdetails.transaction = self.get_raw_tx(txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.get(key)?.map(ivec_to_u32).transpose()
    -    }
    -
    -    fn get_sync_time(&self) -> Result<Option<SyncTime>, Error> {
    -        let key = MapKey::SyncTime.as_map_key();
    -        Ok(self
    -            .get(key)?
    -            .map(|b| serde_json::from_slice(&b))
    -            .transpose()?)
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.update_and_fetch(key, |prev| {
    -            let new = match prev {
    -                Some(b) => {
    -                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
    -                    let val = u32::from_be_bytes(array);
    -
    -                    val + 1
    -                }
    -                None => 0,
    -            };
    -
    -            Some(new.to_be_bytes().to_vec())
    -        })?
    -        .map_or(Ok(0), ivec_to_u32)
    -    }
    -}
    -
    -fn ivec_to_u32(b: sled::IVec) -> Result<u32, Error> {
    -    let array: [u8; 4] = b
    -        .as_ref()
    -        .try_into()
    -        .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -    let val = u32::from_be_bytes(array);
    -    Ok(val)
    -}
    -
    -impl BatchDatabase for Tree {
    -    type Batch = sled::Batch;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        sled::Batch::default()
    -    }
    -
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        Ok(self.apply_batch(batch)?)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use lazy_static::lazy_static;
    -    use std::sync::{Arc, Condvar, Mutex, Once};
    -    use std::time::{SystemTime, UNIX_EPOCH};
    -
    -    use sled::{Db, Tree};
    -
    -    static mut COUNT: usize = 0;
    -
    -    lazy_static! {
    -        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
    -            Arc::new((Mutex::new(None), Condvar::new()));
    -        static ref INIT: Once = Once::new();
    -    }
    -
    -    fn get_tree() -> Tree {
    -        unsafe {
    -            let cloned = DB.clone();
    -            let (mutex, cvar) = &*cloned;
    -
    -            INIT.call_once(|| {
    -                let mut db = mutex.lock().unwrap();
    -
    -                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    -                let mut dir = std::env::temp_dir();
    -                dir.push(format!("mbw_{}", time.as_nanos()));
    -
    -                *db = Some(sled::open(dir).unwrap());
    -                cvar.notify_all();
    -            });
    -
    -            let mut db = mutex.lock().unwrap();
    -            while !db.is_some() {
    -                db = cvar.wait(db).unwrap();
    -            }
    -
    -            COUNT += 1;
    -
    -            db.as_ref()
    -                .unwrap()
    -                .open_tree(format!("tree_{}", COUNT))
    -                .unwrap()
    -        }
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_sync_time() {
    -        crate::database::test::test_sync_time(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_raw_txs() {
    -        crate::database::test::test_iter_raw_txs(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_path_from_script_pubkey() {
    -        crate::database::test::test_del_path_from_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkeys() {
    -        crate::database::test::test_iter_script_pubkeys(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_utxo() {
    -        crate::database::test::test_del_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_raw_tx() {
    -        crate::database::test::test_del_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_tx() {
    -        crate::database::test::test_del_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_last_index() {
    -        crate::database::test::test_del_last_index(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_check_descriptor_checksum() {
    -        crate::database::test::test_check_descriptor_checksum(get_tree());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html deleted file mode 100644 index 7ddcf45124..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html +++ /dev/null @@ -1,1383 +0,0 @@ -memory.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -658
    -659
    -660
    -661
    -662
    -663
    -664
    -665
    -666
    -667
    -668
    -669
    -670
    -671
    -672
    -673
    -674
    -675
    -676
    -677
    -678
    -679
    -680
    -681
    -682
    -683
    -684
    -685
    -686
    -687
    -688
    -689
    -690
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! In-memory ephemeral database
    -//!
    -//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
    -//! [`BTreeMap`].
    -
    -use std::any::Any;
    -use std::collections::BTreeMap;
    -use std::ops::Bound::{Excluded, Included};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::{BatchDatabase, BatchOperations, ConfigurableDatabase, Database, SyncTime};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -// path -> script       p{i,e}<path> -> script
    -// script -> path       s<script> -> {i,e}<path>
    -// outpoint             u<outpoint> -> txout
    -// rawtx                r<txid> -> tx
    -// transactions         t<txid> -> tx details
    -// deriv indexes        c{i,e} -> u32
    -// descriptor checksum  d{i,e} -> vec<u8>
    -// last sync time       l -> { height, timestamp }
    -
    -pub(crate) enum MapKey<'a> {
    -    Path((Option<KeychainKind>, Option<u32>)),
    -    Script(Option<&'a Script>),
    -    Utxo(Option<&'a OutPoint>),
    -    RawTx(Option<&'a Txid>),
    -    Transaction(Option<&'a Txid>),
    -    LastIndex(KeychainKind),
    -    SyncTime,
    -    DescriptorChecksum(KeychainKind),
    -}
    -
    -impl MapKey<'_> {
    -    fn as_prefix(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((st, _)) => {
    -                let mut v = b"p".to_vec();
    -                if let Some(st) = st {
    -                    v.push(st.as_byte());
    -                }
    -                v
    -            }
    -            MapKey::Script(_) => b"s".to_vec(),
    -            MapKey::Utxo(_) => b"u".to_vec(),
    -            MapKey::RawTx(_) => b"r".to_vec(),
    -            MapKey::Transaction(_) => b"t".to_vec(),
    -            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
    -            MapKey::SyncTime => b"l".to_vec(),
    -            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
    -        }
    -    }
    -
    -    fn serialize_content(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((_, Some(child))) => child.to_be_bytes().to_vec(),
    -            MapKey::Script(Some(s)) => serialize(*s),
    -            MapKey::Utxo(Some(s)) => serialize(*s),
    -            MapKey::RawTx(Some(s)) => serialize(*s),
    -            MapKey::Transaction(Some(s)) => serialize(*s),
    -            _ => vec![],
    -        }
    -    }
    -
    -    pub fn as_map_key(&self) -> Vec<u8> {
    -        let mut v = self.as_prefix();
    -        v.extend_from_slice(&self.serialize_content());
    -
    -        v
    -    }
    -}
    -
    -fn after(key: &[u8]) -> Vec<u8> {
    -    let mut key = key.to_owned();
    -    let mut idx = key.len();
    -    while idx > 0 {
    -        if key[idx - 1] == 0xFF {
    -            idx -= 1;
    -            continue;
    -        } else {
    -            key[idx - 1] += 1;
    -            break;
    -        }
    -    }
    -
    -    key
    -}
    -
    -/// In-memory ephemeral database
    -///
    -/// This database can be used as a temporary storage for wallets that are not kept permanently on
    -/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
    -///
    -/// Once it's dropped its content will be lost.
    -///
    -/// If you are looking for a permanent storage solution, you can try with the default key-value
    -/// database called [`sled`]. See the [`database`] module documentation for more details.
    -///
    -/// [`database`]: crate::database
    -#[derive(Debug, Default)]
    -pub struct MemoryDatabase {
    -    map: BTreeMap<Vec<u8>, Box<dyn Any + Send + Sync>>,
    -    deleted_keys: Vec<Vec<u8>>,
    -}
    -
    -impl MemoryDatabase {
    -    /// Create a new empty database
    -    pub fn new() -> Self {
    -        MemoryDatabase {
    -            map: BTreeMap::new(),
    -            deleted_keys: Vec::new(),
    -        }
    -    }
    -}
    -
    -impl BatchOperations for MemoryDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        self.map.insert(key, Box::new(script.clone()));
    -
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let value = json!({
    -            "t": keychain,
    -            "p": path,
    -        });
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
    -        self.map.insert(
    -            key,
    -            Box::new((utxo.txout.clone(), utxo.keychain, utxo.is_spent)),
    -        );
    -
    -        Ok(())
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -        self.map.insert(key, Box::new(transaction.clone()));
    -
    -        Ok(())
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -        // insert the raw_tx if present
    -        if let Some(ref tx) = transaction.transaction {
    -            self.set_raw_tx(tx)?;
    -        }
    -
    -        // remove the raw tx from the serialized version
    -        let mut transaction = transaction.clone();
    -        transaction.transaction = None;
    -
    -        self.map.insert(key, Box::new(transaction));
    -
    -        Ok(())
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -    fn set_sync_time(&mut self, data: SyncTime) -> Result<(), Error> {
    -        let key = MapKey::SyncTime.as_map_key();
    -        self.map.insert(key, Box::new(data));
    -
    -        Ok(())
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok(Some((st, path)))
    -            }
    -        }
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let (txout, keychain, is_spent) = b.downcast_ref().cloned().unwrap();
    -                Ok(Some(LocalUtxo {
    -                    outpoint: *outpoint,
    -                    txout,
    -                    keychain,
    -                    is_spent,
    -                }))
    -            }
    -        }
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        let raw_tx = if include_raw {
    -            self.del_raw_tx(txid)?
    -        } else {
    -            None
    -        };
    -
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -                val.transaction = raw_tx;
    -
    -                Ok(Some(val))
    -            }
    -        }
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
    -        }
    -    }
    -    fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error> {
    -        let key = MapKey::SyncTime.as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -}
    -
    -impl Database for MemoryDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
    -
    -        let prev = self
    -            .map
    -            .get(&key)
    -            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
    -        if let Some(val) = prev {
    -            if val == &bytes.as_ref().to_vec() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((keychain, None)).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let outpoint = deserialize(&k[1..]).unwrap();
    -                let (txout, keychain, is_spent) = v.downcast_ref().cloned().unwrap();
    -                Ok(LocalUtxo {
    -                    outpoint,
    -                    txout,
    -                    keychain,
    -                    is_spent,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -            let st = serde_json::from_value(val["t"].take()).unwrap();
    -            let path = serde_json::from_value(val["p"].take()).unwrap();
    -
    -            (st, path)
    -        }))
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let (txout, keychain, is_spent) = b.downcast_ref().cloned().unwrap();
    -            LocalUtxo {
    -                outpoint: *outpoint,
    -                txout,
    -                keychain,
    -                is_spent,
    -            }
    -        }))
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -            if include_raw {
    -                txdetails.transaction = self.get_raw_tx(txid).unwrap();
    -            }
    -
    -            txdetails
    -        }))
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
    -    }
    -
    -    fn get_sync_time(&self) -> Result<Option<SyncTime>, Error> {
    -        let key = MapKey::SyncTime.as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        let value = self
    -            .map
    -            .entry(key)
    -            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
    -            .or_insert_with(|| Box::<u32>::new(0))
    -            .downcast_mut()
    -            .unwrap();
    -
    -        Ok(*value)
    -    }
    -}
    -
    -impl BatchDatabase for MemoryDatabase {
    -    type Batch = Self;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        MemoryDatabase::new()
    -    }
    -
    -    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
    -        for key in batch.deleted_keys.iter() {
    -            self.map.remove(key);
    -        }
    -        self.map.append(&mut batch.map);
    -        Ok(())
    -    }
    -}
    -
    -impl ConfigurableDatabase for MemoryDatabase {
    -    type Config = ();
    -
    -    fn from_config(_config: &Self::Config) -> Result<Self, Error> {
    -        Ok(MemoryDatabase::default())
    -    }
    -}
    -
    -#[macro_export]
    -#[doc(hidden)]
    -/// Artificially insert a tx in the database, as if we had found it with a `sync`. This is a hidden
    -/// macro and not a `[cfg(test)]` function so it can be called within the context of doctests which
    -/// don't have `test` set.
    -macro_rules! populate_test_db {
    -    ($db:expr, $tx_meta:expr, $current_height:expr$(,)?) => {{
    -        $crate::populate_test_db!($db, $tx_meta, $current_height, (@coinbase false))
    -    }};
    -    ($db:expr, $tx_meta:expr, $current_height:expr, (@coinbase $is_coinbase:expr)$(,)?) => {{
    -        use std::str::FromStr;
    -        use $crate::database::SyncTime;
    -        use $crate::database::{BatchOperations, Database};
    -        let mut db = $db;
    -        let tx_meta = $tx_meta;
    -        let current_height: Option<u32> = $current_height;
    -        let mut input = vec![$crate::bitcoin::TxIn::default()];
    -        if !$is_coinbase {
    -            input[0].previous_output.vout = 0;
    -        }
    -        let tx = $crate::bitcoin::Transaction {
    -            version: 1,
    -            lock_time: bitcoin::PackedLockTime(0),
    -            input,
    -            output: tx_meta
    -                .output
    -                .iter()
    -                .map(|out_meta| $crate::bitcoin::TxOut {
    -                    value: out_meta.value,
    -                    script_pubkey: $crate::bitcoin::Address::from_str(&out_meta.to_address)
    -                        .unwrap()
    -                        .script_pubkey(),
    -                })
    -                .collect(),
    -        };
    -
    -        let txid = tx.txid();
    -        // Set Confirmation time only if current height is provided.
    -        // panics if `tx_meta.min_confirmation` is Some, and current_height is None.
    -        let confirmation_time = tx_meta
    -            .min_confirmations
    -            .and_then(|v| if v == 0 { None } else { Some(v) })
    -            .map(|conf| $crate::BlockTime {
    -                height: current_height.expect("Current height is needed for testing transaction with min-confirmation values").checked_sub(conf as u32).unwrap() + 1,
    -                timestamp: 0,
    -            });
    -
    -        // Set the database sync_time.
    -        // Check if the current_height is less than already known sync height, apply the max
    -        // If any of them is None, the other will be applied instead.
    -        // If both are None, this will not be set.
    -        if let Some(height) = db.get_sync_time().unwrap()
    -                                .map(|sync_time| sync_time.block_time.height)
    -                                .max(current_height) {
    -            let sync_time = SyncTime {
    -                block_time: BlockTime {
    -                    height,
    -                    timestamp: 0
    -                }
    -            };
    -            db.set_sync_time(sync_time).unwrap();
    -        }
    -
    -        let tx_details = $crate::TransactionDetails {
    -            transaction: Some(tx.clone()),
    -            txid,
    -            fee: Some(0),
    -            received: 0,
    -            sent: 0,
    -            confirmation_time,
    -        };
    -
    -        db.set_tx(&tx_details).unwrap();
    -        for (vout, out) in tx.output.iter().enumerate() {
    -            db.set_utxo(&$crate::LocalUtxo {
    -                txout: out.clone(),
    -                outpoint: $crate::bitcoin::OutPoint {
    -                    txid,
    -                    vout: vout as u32,
    -                },
    -                keychain: $crate::KeychainKind::External,
    -                is_spent: false,
    -            })
    -            .unwrap();
    -        }
    -
    -        txid
    -    }};
    -}
    -
    -#[macro_export]
    -#[doc(hidden)]
    -/// Macro for getting a wallet for use in a doctest
    -macro_rules! doctest_wallet {
    -    () => {{
    -        use $crate::bitcoin::Network;
    -        use $crate::database::MemoryDatabase;
    -        use $crate::testutils;
    -        let descriptor = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
    -        let descriptors = testutils!(@descriptors (descriptor) (descriptor));
    -
    -        let mut db = MemoryDatabase::new();
    -        let txid = populate_test_db!(
    -            &mut db,
    -            testutils! {
    -                @tx ( (@external descriptors, 0) => 500_000 ) (@confirmations 1)
    -            },
    -            Some(100),
    -        );
    -
    -        $crate::Wallet::new(
    -            &descriptors.0,
    -            descriptors.1.as_ref(),
    -            Network::Regtest,
    -            db
    -        )
    -        .unwrap()
    -    }}
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::MemoryDatabase;
    -
    -    fn get_tree() -> MemoryDatabase {
    -        MemoryDatabase::new()
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_sync_time() {
    -        crate::database::test::test_sync_time(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_raw_txs() {
    -        crate::database::test::test_iter_raw_txs(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_path_from_script_pubkey() {
    -        crate::database::test::test_del_path_from_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkeys() {
    -        crate::database::test::test_iter_script_pubkeys(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_utxo() {
    -        crate::database::test::test_del_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_raw_tx() {
    -        crate::database::test::test_del_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_tx() {
    -        crate::database::test::test_del_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_last_index() {
    -        crate::database::test::test_del_last_index(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_check_descriptor_checksum() {
    -        crate::database::test::test_check_descriptor_checksum(get_tree());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html deleted file mode 100644 index 9d642cb9db..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html +++ /dev/null @@ -1,1317 +0,0 @@ -mod.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Database types
    -//!
    -//! This module provides the implementation of some defaults database types, along with traits that
    -//! can be implemented externally to let [`Wallet`]s use customized databases.
    -//!
    -//! It's important to note that the databases defined here only contains "blockchain-related" data.
    -//! They can be seen more as a cache than a critical piece of storage that contains secrets and
    -//! keys.
    -//!
    -//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
    -//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
    -//! this library automatically implements all the required traits for [`sled::Tree`].
    -//!
    -//! [`Wallet`]: crate::wallet::Wallet
    -
    -use serde::{Deserialize, Serialize};
    -
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction, TxOut};
    -
    -use crate::error::Error;
    -use crate::types::*;
    -
    -pub mod any;
    -pub use any::{AnyDatabase, AnyDatabaseConfig};
    -
    -#[cfg(feature = "key-value-db")]
    -pub(crate) mod keyvalue;
    -
    -#[cfg(feature = "sqlite")]
    -pub(crate) mod sqlite;
    -#[cfg(feature = "sqlite")]
    -pub use sqlite::SqliteDatabase;
    -
    -pub mod memory;
    -pub use memory::MemoryDatabase;
    -
    -/// Blockchain state at the time of syncing
    -///
    -/// Contains only the block time and height at the moment
    -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
    -pub struct SyncTime {
    -    /// Block timestamp and height at the time of sync
    -    pub block_time: BlockTime,
    -}
    -
    -/// Trait for operations that can be batched
    -///
    -/// This trait defines the list of operations that must be implemented on the [`Database`] type and
    -/// the [`BatchDatabase::Batch`] type.
    -pub trait BatchOperations {
    -    /// Store a script_pubkey along with its keychain and child number.
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error>;
    -    /// Store a [`LocalUtxo`]
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error>;
    -    /// Store a raw transaction
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
    -    /// Store the metadata of a transaction
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
    -    /// Store the last derivation index for a given keychain.
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error>;
    -    /// Store the sync time
    -    fn set_sync_time(&mut self, sync_time: SyncTime) -> Result<(), Error>;
    -
    -    /// Delete a script_pubkey given the keychain and its child number.
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Delete the data related to a specific script_pubkey, meaning the keychain and the child
    -    /// number.
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error>;
    -    /// Delete a [`LocalUtxo`] given its [`OutPoint`]
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>;
    -    /// Delete a raw transaction given its [`Txid`]
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Delete the metadata of a transaction and optionally the raw transaction itself
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error>;
    -    /// Delete the last derivation index for a keychain.
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
    -    /// Reset the sync time to `None`
    -    ///
    -    /// Returns the removed value
    -    fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error>;
    -}
    -
    -/// Trait for reading data from a database
    -///
    -/// This traits defines the operations that can be used to read data out of a database
    -pub trait Database: BatchOperations {
    -    /// Read and checks the descriptor checksum for a given keychain.
    -    ///
    -    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
    -    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
    -    /// next time.
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error>;
    -
    -    /// Return the list of script_pubkeys
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error>;
    -    /// Return the list of [`LocalUtxo`]s
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error>;
    -    /// Return the list of raw transactions
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
    -    /// Return the list of transactions metadata
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
    -
    -    /// Fetch a script_pubkey given the child number of a keychain.
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Fetch the keychain and child number of a given script_pubkey
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error>;
    -    /// Fetch a [`LocalUtxo`] given its [`OutPoint`]
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>;
    -    /// Fetch a raw transaction given its [`Txid`]
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Fetch the transaction metadata and optionally also the raw transaction
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
    -    /// Return the last derivation index for a keychain.
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
    -    /// Return the sync time, if present
    -    fn get_sync_time(&self) -> Result<Option<SyncTime>, Error>;
    -
    -    /// Increment the last derivation index for a keychain and return it
    -    ///
    -    /// It should insert and return `0` if not present in the database
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error>;
    -}
    -
    -/// Trait for a database that supports batch operations
    -///
    -/// This trait defines the methods to start and apply a batch of operations.
    -pub trait BatchDatabase: Database {
    -    /// Container for the operations
    -    type Batch: BatchOperations;
    -
    -    /// Create a new batch container
    -    fn begin_batch(&self) -> Self::Batch;
    -    /// Consume and apply a batch of operations
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
    -}
    -
    -/// Trait for [`Database`] types that can be created given a configuration
    -pub trait ConfigurableDatabase: Database + Sized {
    -    /// Type that contains the configuration
    -    type Config: std::fmt::Debug;
    -
    -    /// Create a new instance given a configuration
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    -
    -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())
    -    }
    -
    -    fn get_raw_tx_or<D>(&self, txid: &Txid, default: D) -> Result<Option<Transaction>, Error>
    -    where
    -        D: FnOnce() -> Result<Option<Transaction>, Error>,
    -    {
    -        self.get_tx(txid, true)?
    -            .and_then(|t| t.transaction)
    -            .map_or_else(default, |t| Ok(Some(t)))
    -    }
    -
    -    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
    -        self.get_raw_tx(&outpoint.txid)?
    -            .map(|previous_tx| {
    -                if outpoint.vout as usize >= previous_tx.output.len() {
    -                    Err(Error::InvalidOutpoint(*outpoint))
    -                } else {
    -                    Ok(previous_tx.output[outpoint.vout as usize].clone())
    -                }
    -            })
    -            .transpose()
    -    }
    -}
    -
    -impl<T: Database> DatabaseUtils for T {}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::consensus::serialize;
    -    use bitcoin::hashes::hex::*;
    -    use bitcoin::*;
    -
    -    use super::*;
    -
    -    pub fn test_script_pubkey<D: Database>(mut db: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        db.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(
    -            db.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            db.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((keychain, path))
    -        );
    -    }
    -
    -    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut db: D) {
    -        let mut batch = db.begin_batch();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        batch.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(
    -            db.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            None
    -        );
    -        assert_eq!(db.get_path_from_script_pubkey(&script).unwrap(), None);
    -
    -        db.commit_batch(batch).unwrap();
    -
    -        assert_eq!(
    -            db.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            db.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((keychain, path))
    -        );
    -    }
    -
    -    pub fn test_iter_script_pubkey<D: Database>(mut db: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        db.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(db.iter_script_pubkeys(None).unwrap().len(), 1);
    -    }
    -
    -    pub fn test_del_script_pubkey<D: Database>(mut db: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        db.set_script_pubkey(&script, keychain, path).unwrap();
    -        assert_eq!(db.iter_script_pubkeys(None).unwrap().len(), 1);
    -
    -        db.del_script_pubkey_from_path(keychain, path).unwrap();
    -        assert_eq!(db.iter_script_pubkeys(None).unwrap().len(), 0);
    -    }
    -
    -    pub fn test_utxo<D: Database>(mut db: D) {
    -        let outpoint = OutPoint::from_str(
    -            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
    -        )
    -        .unwrap();
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let txout = TxOut {
    -            value: 133742,
    -            script_pubkey: script,
    -        };
    -        let utxo = LocalUtxo {
    -            txout,
    -            outpoint,
    -            keychain: KeychainKind::External,
    -            is_spent: true,
    -        };
    -
    -        db.set_utxo(&utxo).unwrap();
    -        db.set_utxo(&utxo).unwrap();
    -        assert_eq!(db.iter_utxos().unwrap().len(), 1);
    -        assert_eq!(db.get_utxo(&outpoint).unwrap(), Some(utxo));
    -    }
    -
    -    pub fn test_raw_tx<D: Database>(mut db: D) {
    -        let hex_tx = Vec::<u8>::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap();
    -        let mut tx: Transaction = deserialize(&hex_tx).unwrap();
    -
    -        db.set_raw_tx(&tx).unwrap();
    -
    -        let txid = tx.txid();
    -
    -        assert_eq!(db.get_raw_tx(&txid).unwrap(), Some(tx.clone()));
    -
    -        // mutate transaction's witnesses
    -        for tx_in in tx.input.iter_mut() {
    -            tx_in.witness = Witness::new();
    -        }
    -
    -        let updated_hex_tx = serialize(&tx);
    -
    -        // verify that mutation was successful
    -        assert_ne!(hex_tx, updated_hex_tx);
    -
    -        db.set_raw_tx(&tx).unwrap();
    -
    -        let txid = tx.txid();
    -
    -        assert_eq!(db.get_raw_tx(&txid).unwrap(), Some(tx));
    -    }
    -
    -    pub fn test_tx<D: Database>(mut db: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -        let txid = tx.txid();
    -        let mut tx_details = TransactionDetails {
    -            transaction: Some(tx),
    -            txid,
    -            received: 1337,
    -            sent: 420420,
    -            fee: Some(140),
    -            confirmation_time: Some(BlockTime {
    -                timestamp: 123456,
    -                height: 1000,
    -            }),
    -        };
    -
    -        db.set_tx(&tx_details).unwrap();
    -
    -        // get with raw tx too
    -        assert_eq!(
    -            db.get_tx(&tx_details.txid, true).unwrap(),
    -            Some(tx_details.clone())
    -        );
    -        // get only raw_tx
    -        assert_eq!(
    -            db.get_raw_tx(&tx_details.txid).unwrap(),
    -            tx_details.transaction
    -        );
    -
    -        // now get without raw_tx
    -        tx_details.transaction = None;
    -        assert_eq!(
    -            db.get_tx(&tx_details.txid, false).unwrap(),
    -            Some(tx_details)
    -        );
    -    }
    -
    -    pub fn test_list_transaction<D: Database>(mut db: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -        let txid = tx.txid();
    -        let mut tx_details = TransactionDetails {
    -            transaction: Some(tx),
    -            txid,
    -            received: 1337,
    -            sent: 420420,
    -            fee: Some(140),
    -            confirmation_time: Some(BlockTime {
    -                timestamp: 123456,
    -                height: 1000,
    -            }),
    -        };
    -
    -        db.set_tx(&tx_details).unwrap();
    -
    -        // get raw tx
    -        assert_eq!(db.iter_txs(true).unwrap(), vec![tx_details.clone()]);
    -
    -        // now get without raw tx
    -        tx_details.transaction = None;
    -
    -        // get not raw tx
    -        assert_eq!(db.iter_txs(false).unwrap(), vec![tx_details.clone()]);
    -    }
    -
    -    pub fn test_last_index<D: Database>(mut db: D) {
    -        db.set_last_index(KeychainKind::External, 1337).unwrap();
    -
    -        assert_eq!(
    -            db.get_last_index(KeychainKind::External).unwrap(),
    -            Some(1337)
    -        );
    -        assert_eq!(db.get_last_index(KeychainKind::Internal).unwrap(), None);
    -
    -        let res = db.increment_last_index(KeychainKind::External).unwrap();
    -        assert_eq!(res, 1338);
    -        let res = db.increment_last_index(KeychainKind::Internal).unwrap();
    -        assert_eq!(res, 0);
    -
    -        assert_eq!(
    -            db.get_last_index(KeychainKind::External).unwrap(),
    -            Some(1338)
    -        );
    -        assert_eq!(db.get_last_index(KeychainKind::Internal).unwrap(), Some(0));
    -    }
    -
    -    pub fn test_sync_time<D: Database>(mut db: D) {
    -        assert!(db.get_sync_time().unwrap().is_none());
    -
    -        db.set_sync_time(SyncTime {
    -            block_time: BlockTime {
    -                height: 100,
    -                timestamp: 1000,
    -            },
    -        })
    -        .unwrap();
    -
    -        let extracted = db.get_sync_time().unwrap();
    -        assert!(extracted.is_some());
    -        assert_eq!(extracted.as_ref().unwrap().block_time.height, 100);
    -        assert_eq!(extracted.as_ref().unwrap().block_time.timestamp, 1000);
    -
    -        db.del_sync_time().unwrap();
    -        assert!(db.get_sync_time().unwrap().is_none());
    -    }
    -
    -    pub fn test_iter_raw_txs<D: Database>(mut db: D) {
    -        let txs = db.iter_raw_txs().unwrap();
    -        assert!(txs.is_empty());
    -
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let first_tx: Transaction = deserialize(&hex_tx).unwrap();
    -
    -        let hex_tx = Vec::<u8>::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap();
    -        let second_tx: Transaction = deserialize(&hex_tx).unwrap();
    -
    -        db.set_raw_tx(&first_tx).unwrap();
    -        db.set_raw_tx(&second_tx).unwrap();
    -
    -        let txs = db.iter_raw_txs().unwrap();
    -
    -        assert!(txs.contains(&first_tx));
    -        assert!(txs.contains(&second_tx));
    -        assert_eq!(txs.len(), 2);
    -    }
    -
    -    pub fn test_del_path_from_script_pubkey<D: Database>(mut db: D) {
    -        let keychain = KeychainKind::External;
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -
    -        let res = db.del_path_from_script_pubkey(&script).unwrap();
    -
    -        assert!(res.is_none());
    -
    -        db.set_script_pubkey(&script, keychain, path).unwrap();
    -        let (chain, child) = db.del_path_from_script_pubkey(&script).unwrap().unwrap();
    -
    -        assert_eq!(chain, keychain);
    -        assert_eq!(child, path);
    -
    -        let res = db.get_path_from_script_pubkey(&script).unwrap();
    -        assert!(res.is_none());
    -    }
    -
    -    pub fn test_iter_script_pubkeys<D: Database>(mut db: D) {
    -        let keychain = KeychainKind::External;
    -        let scripts = db.iter_script_pubkeys(Some(keychain)).unwrap();
    -        assert!(scripts.is_empty());
    -
    -        let first_script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -
    -        db.set_script_pubkey(&first_script, keychain, path).unwrap();
    -
    -        let second_script = Script::from(
    -            Vec::<u8>::from_hex("00145c9a1816d38db5cbdd4b067b689dc19eb7d930e2").unwrap(),
    -        );
    -        let path = 57;
    -
    -        db.set_script_pubkey(&second_script, keychain, path)
    -            .unwrap();
    -        let scripts = db.iter_script_pubkeys(Some(keychain)).unwrap();
    -
    -        assert!(scripts.contains(&first_script));
    -        assert!(scripts.contains(&second_script));
    -        assert_eq!(scripts.len(), 2);
    -    }
    -
    -    pub fn test_del_utxo<D: Database>(mut db: D) {
    -        let outpoint = OutPoint::from_str(
    -            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
    -        )
    -        .unwrap();
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let txout = TxOut {
    -            value: 133742,
    -            script_pubkey: script,
    -        };
    -        let utxo = LocalUtxo {
    -            txout,
    -            outpoint,
    -            keychain: KeychainKind::External,
    -            is_spent: true,
    -        };
    -
    -        let res = db.del_utxo(&outpoint).unwrap();
    -        assert!(res.is_none());
    -
    -        db.set_utxo(&utxo).unwrap();
    -
    -        let res = db.del_utxo(&outpoint).unwrap();
    -
    -        assert_eq!(res.unwrap(), utxo);
    -
    -        let res = db.get_utxo(&outpoint).unwrap();
    -        assert!(res.is_none());
    -    }
    -
    -    pub fn test_del_raw_tx<D: Database>(mut db: D) {
    -        let hex_tx = Vec::<u8>::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -
    -        let res = db.del_raw_tx(&tx.txid()).unwrap();
    -
    -        assert!(res.is_none());
    -
    -        db.set_raw_tx(&tx).unwrap();
    -
    -        let res = db.del_raw_tx(&tx.txid()).unwrap();
    -
    -        assert_eq!(res.unwrap(), tx);
    -
    -        let res = db.get_raw_tx(&tx.txid()).unwrap();
    -        assert!(res.is_none());
    -    }
    -
    -    pub fn test_del_tx<D: Database>(mut db: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -        let txid = tx.txid();
    -        let mut tx_details = TransactionDetails {
    -            transaction: Some(tx.clone()),
    -            txid,
    -            received: 1337,
    -            sent: 420420,
    -            fee: Some(140),
    -            confirmation_time: Some(BlockTime {
    -                timestamp: 123456,
    -                height: 1000,
    -            }),
    -        };
    -
    -        let res = db.del_tx(&tx.txid(), true).unwrap();
    -
    -        assert!(res.is_none());
    -
    -        db.set_tx(&tx_details).unwrap();
    -
    -        let res = db.del_tx(&tx.txid(), false).unwrap();
    -        tx_details.transaction = None;
    -        assert_eq!(res.unwrap(), tx_details);
    -
    -        let res = db.get_tx(&tx.txid(), true).unwrap();
    -        assert!(res.is_none());
    -
    -        let res = db.get_raw_tx(&tx.txid()).unwrap();
    -        assert_eq!(res.unwrap(), tx);
    -
    -        db.set_tx(&tx_details).unwrap();
    -        let res = db.del_tx(&tx.txid(), true).unwrap();
    -        tx_details.transaction = Some(tx.clone());
    -        assert_eq!(res.unwrap(), tx_details);
    -
    -        let res = db.get_tx(&tx.txid(), true).unwrap();
    -        assert!(res.is_none());
    -
    -        let res = db.get_raw_tx(&tx.txid()).unwrap();
    -        assert!(res.is_none());
    -    }
    -
    -    pub fn test_del_last_index<D: Database>(mut db: D) {
    -        let keychain = KeychainKind::External;
    -
    -        db.increment_last_index(keychain).unwrap();
    -
    -        let res = db.get_last_index(keychain).unwrap().unwrap();
    -
    -        assert_eq!(res, 0);
    -
    -        db.increment_last_index(keychain).unwrap();
    -
    -        let res = db.del_last_index(keychain).unwrap().unwrap();
    -
    -        assert_eq!(res, 1);
    -
    -        let res = db.get_last_index(keychain).unwrap();
    -        assert!(res.is_none());
    -    }
    -
    -    pub fn test_check_descriptor_checksum<D: Database>(mut db: D) {
    -        // insert checksum associated to keychain
    -        let checksum = "1cead456".as_bytes();
    -        let keychain = KeychainKind::External;
    -        db.check_descriptor_checksum(keychain, checksum).unwrap();
    -
    -        // check if `check_descriptor_checksum` throws
    -        // `Error::ChecksumMismatch` error if the
    -        // function is passed a checksum that does
    -        // not match the one initially inserted
    -        let checksum = "1cead454".as_bytes();
    -        let keychain = KeychainKind::External;
    -        let res = db.check_descriptor_checksum(keychain, checksum);
    -
    -        assert!(res.is_err());
    -    }
    -
    -    // TODO: more tests...
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html deleted file mode 100644 index c15449fc52..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html +++ /dev/null @@ -1,2297 +0,0 @@ -sqlite.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -658
    -659
    -660
    -661
    -662
    -663
    -664
    -665
    -666
    -667
    -668
    -669
    -670
    -671
    -672
    -673
    -674
    -675
    -676
    -677
    -678
    -679
    -680
    -681
    -682
    -683
    -684
    -685
    -686
    -687
    -688
    -689
    -690
    -691
    -692
    -693
    -694
    -695
    -696
    -697
    -698
    -699
    -700
    -701
    -702
    -703
    -704
    -705
    -706
    -707
    -708
    -709
    -710
    -711
    -712
    -713
    -714
    -715
    -716
    -717
    -718
    -719
    -720
    -721
    -722
    -723
    -724
    -725
    -726
    -727
    -728
    -729
    -730
    -731
    -732
    -733
    -734
    -735
    -736
    -737
    -738
    -739
    -740
    -741
    -742
    -743
    -744
    -745
    -746
    -747
    -748
    -749
    -750
    -751
    -752
    -753
    -754
    -755
    -756
    -757
    -758
    -759
    -760
    -761
    -762
    -763
    -764
    -765
    -766
    -767
    -768
    -769
    -770
    -771
    -772
    -773
    -774
    -775
    -776
    -777
    -778
    -779
    -780
    -781
    -782
    -783
    -784
    -785
    -786
    -787
    -788
    -789
    -790
    -791
    -792
    -793
    -794
    -795
    -796
    -797
    -798
    -799
    -800
    -801
    -802
    -803
    -804
    -805
    -806
    -807
    -808
    -809
    -810
    -811
    -812
    -813
    -814
    -815
    -816
    -817
    -818
    -819
    -820
    -821
    -822
    -823
    -824
    -825
    -826
    -827
    -828
    -829
    -830
    -831
    -832
    -833
    -834
    -835
    -836
    -837
    -838
    -839
    -840
    -841
    -842
    -843
    -844
    -845
    -846
    -847
    -848
    -849
    -850
    -851
    -852
    -853
    -854
    -855
    -856
    -857
    -858
    -859
    -860
    -861
    -862
    -863
    -864
    -865
    -866
    -867
    -868
    -869
    -870
    -871
    -872
    -873
    -874
    -875
    -876
    -877
    -878
    -879
    -880
    -881
    -882
    -883
    -884
    -885
    -886
    -887
    -888
    -889
    -890
    -891
    -892
    -893
    -894
    -895
    -896
    -897
    -898
    -899
    -900
    -901
    -902
    -903
    -904
    -905
    -906
    -907
    -908
    -909
    -910
    -911
    -912
    -913
    -914
    -915
    -916
    -917
    -918
    -919
    -920
    -921
    -922
    -923
    -924
    -925
    -926
    -927
    -928
    -929
    -930
    -931
    -932
    -933
    -934
    -935
    -936
    -937
    -938
    -939
    -940
    -941
    -942
    -943
    -944
    -945
    -946
    -947
    -948
    -949
    -950
    -951
    -952
    -953
    -954
    -955
    -956
    -957
    -958
    -959
    -960
    -961
    -962
    -963
    -964
    -965
    -966
    -967
    -968
    -969
    -970
    -971
    -972
    -973
    -974
    -975
    -976
    -977
    -978
    -979
    -980
    -981
    -982
    -983
    -984
    -985
    -986
    -987
    -988
    -989
    -990
    -991
    -992
    -993
    -994
    -995
    -996
    -997
    -998
    -999
    -1000
    -1001
    -1002
    -1003
    -1004
    -1005
    -1006
    -1007
    -1008
    -1009
    -1010
    -1011
    -1012
    -1013
    -1014
    -1015
    -1016
    -1017
    -1018
    -1019
    -1020
    -1021
    -1022
    -1023
    -1024
    -1025
    -1026
    -1027
    -1028
    -1029
    -1030
    -1031
    -1032
    -1033
    -1034
    -1035
    -1036
    -1037
    -1038
    -1039
    -1040
    -1041
    -1042
    -1043
    -1044
    -1045
    -1046
    -1047
    -1048
    -1049
    -1050
    -1051
    -1052
    -1053
    -1054
    -1055
    -1056
    -1057
    -1058
    -1059
    -1060
    -1061
    -1062
    -1063
    -1064
    -1065
    -1066
    -1067
    -1068
    -1069
    -1070
    -1071
    -1072
    -1073
    -1074
    -1075
    -1076
    -1077
    -1078
    -1079
    -1080
    -1081
    -1082
    -1083
    -1084
    -1085
    -1086
    -1087
    -1088
    -1089
    -1090
    -1091
    -1092
    -1093
    -1094
    -1095
    -1096
    -1097
    -1098
    -1099
    -1100
    -1101
    -1102
    -1103
    -1104
    -1105
    -1106
    -1107
    -1108
    -1109
    -1110
    -1111
    -1112
    -1113
    -1114
    -1115
    -1116
    -1117
    -1118
    -1119
    -1120
    -1121
    -1122
    -1123
    -1124
    -1125
    -1126
    -1127
    -1128
    -1129
    -1130
    -1131
    -1132
    -1133
    -1134
    -1135
    -1136
    -1137
    -1138
    -1139
    -1140
    -1141
    -1142
    -1143
    -1144
    -1145
    -1146
    -1147
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -use std::path::Path;
    -use std::path::PathBuf;
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction, TxOut};
    -
    -use crate::database::{BatchDatabase, BatchOperations, Database, SyncTime};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -use rusqlite::{named_params, Connection};
    -
    -static MIGRATIONS: &[&str] = &[
    -    "CREATE TABLE version (version INTEGER)",
    -    "INSERT INTO version VALUES (1)",
    -    "CREATE TABLE script_pubkeys (keychain TEXT, child INTEGER, script BLOB);",
    -    "CREATE INDEX idx_keychain_child ON script_pubkeys(keychain, child);",
    -    "CREATE INDEX idx_script ON script_pubkeys(script);",
    -    "CREATE TABLE utxos (value INTEGER, keychain TEXT, vout INTEGER, txid BLOB, script BLOB);",
    -    "CREATE INDEX idx_txid_vout ON utxos(txid, vout);",
    -    "CREATE TABLE transactions (txid BLOB, raw_tx BLOB);",
    -    "CREATE INDEX idx_txid ON transactions(txid);",
    -    "CREATE TABLE transaction_details (txid BLOB, timestamp INTEGER, received INTEGER, sent INTEGER, fee INTEGER, height INTEGER, verified INTEGER DEFAULT 0);",
    -    "CREATE INDEX idx_txdetails_txid ON transaction_details(txid);",
    -    "CREATE TABLE last_derivation_indices (keychain TEXT, value INTEGER);",
    -    "CREATE UNIQUE INDEX idx_indices_keychain ON last_derivation_indices(keychain);",
    -    "CREATE TABLE checksums (keychain TEXT, checksum BLOB);",
    -    "CREATE INDEX idx_checksums_keychain ON checksums(keychain);",
    -    "CREATE TABLE sync_time (id INTEGER PRIMARY KEY, height INTEGER, timestamp INTEGER);",
    -    "ALTER TABLE transaction_details RENAME TO transaction_details_old;",
    -    "CREATE TABLE transaction_details (txid BLOB, timestamp INTEGER, received INTEGER, sent INTEGER, fee INTEGER, height INTEGER);",
    -    "INSERT INTO transaction_details SELECT txid, timestamp, received, sent, fee, height FROM transaction_details_old;",
    -    "DROP TABLE transaction_details_old;",
    -    "ALTER TABLE utxos ADD COLUMN is_spent;",
    -    // drop all data due to possible inconsistencies with duplicate utxos, re-sync required
    -    "DELETE FROM checksums;",
    -    "DELETE FROM last_derivation_indices;",
    -    "DELETE FROM script_pubkeys;",
    -    "DELETE FROM sync_time;",
    -    "DELETE FROM transaction_details;",
    -    "DELETE FROM transactions;",
    -    "DELETE FROM utxos;",
    -    "DROP INDEX idx_txid_vout;",
    -    "CREATE UNIQUE INDEX idx_utxos_txid_vout ON utxos(txid, vout);",
    -    "ALTER TABLE utxos RENAME TO utxos_old;",
    -    "CREATE TABLE utxos (value INTEGER, keychain TEXT, vout INTEGER, txid BLOB, script BLOB, is_spent BOOLEAN DEFAULT 0);",
    -    "INSERT INTO utxos SELECT value, keychain, vout, txid, script, is_spent FROM utxos_old;",
    -    "DROP TABLE utxos_old;",
    -    "CREATE UNIQUE INDEX idx_utxos_txid_vout ON utxos(txid, vout);",
    -    // Fix issue https://github.com/bitcoindevkit/bdk/issues/801: drop duplicated script_pubkeys
    -    "ALTER TABLE script_pubkeys RENAME TO script_pubkeys_old;",
    -    "DROP INDEX idx_keychain_child;",
    -    "DROP INDEX idx_script;",
    -    "CREATE TABLE script_pubkeys (keychain TEXT, child INTEGER, script BLOB);",
    -    "CREATE INDEX idx_keychain_child ON script_pubkeys(keychain, child);",
    -    "CREATE INDEX idx_script ON script_pubkeys(script);",
    -    "CREATE UNIQUE INDEX idx_script_pks_unique ON script_pubkeys(keychain, child);",
    -    "INSERT OR REPLACE INTO script_pubkeys SELECT keychain, child, script FROM script_pubkeys_old;",
    -    "DROP TABLE script_pubkeys_old;"
    -];
    -
    -/// Sqlite database stored on filesystem
    -///
    -/// This is a permanent storage solution for devices and platforms that provide a filesystem.
    -/// [`crate::database`]
    -#[derive(Debug)]
    -pub struct SqliteDatabase {
    -    /// Path on the local filesystem to store the sqlite file
    -    pub path: PathBuf,
    -    /// A rusqlite connection object to the sqlite database
    -    pub connection: Connection,
    -}
    -
    -impl SqliteDatabase {
    -    /// Instantiate a new SqliteDatabase instance by creating a connection
    -    /// to the database stored at path
    -    pub fn new<T: AsRef<Path>>(path: T) -> Self {
    -        let connection = get_connection(&path).unwrap();
    -        SqliteDatabase {
    -            path: PathBuf::from(path.as_ref()),
    -            connection,
    -        }
    -    }
    -    fn insert_script_pubkey(
    -        &self,
    -        keychain: String,
    -        child: u32,
    -        script: &[u8],
    -    ) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached("INSERT OR REPLACE INTO script_pubkeys (keychain, child, script) VALUES (:keychain, :child, :script)")?;
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":child": child,
    -            ":script": script
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -    fn insert_utxo(
    -        &self,
    -        value: u64,
    -        keychain: String,
    -        vout: u32,
    -        txid: &[u8],
    -        script: &[u8],
    -        is_spent: bool,
    -    ) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached("INSERT INTO utxos (value, keychain, vout, txid, script, is_spent) VALUES (:value, :keychain, :vout, :txid, :script, :is_spent) ON CONFLICT(txid, vout) DO UPDATE SET value=:value, keychain=:keychain, script=:script, is_spent=:is_spent")?;
    -        statement.execute(named_params! {
    -            ":value": value,
    -            ":keychain": keychain,
    -            ":vout": vout,
    -            ":txid": txid,
    -            ":script": script,
    -            ":is_spent": is_spent,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -    fn insert_transaction(&self, txid: &[u8], raw_tx: &[u8]) -> Result<i64, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("INSERT INTO transactions (txid, raw_tx) VALUES (:txid, :raw_tx)")?;
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":raw_tx": raw_tx,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn update_transaction(&self, txid: &[u8], raw_tx: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("UPDATE transactions SET raw_tx=:raw_tx WHERE txid=:txid")?;
    -
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":raw_tx": raw_tx,
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn insert_transaction_details(&self, transaction: &TransactionDetails) -> Result<i64, Error> {
    -        let (timestamp, height) = match &transaction.confirmation_time {
    -            Some(confirmation_time) => (
    -                Some(confirmation_time.timestamp),
    -                Some(confirmation_time.height),
    -            ),
    -            None => (None, None),
    -        };
    -
    -        let txid: &[u8] = &transaction.txid;
    -
    -        let mut statement = self.connection.prepare_cached("INSERT INTO transaction_details (txid, timestamp, received, sent, fee, height) VALUES (:txid, :timestamp, :received, :sent, :fee, :height)")?;
    -
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":timestamp": timestamp,
    -            ":received": transaction.received,
    -            ":sent": transaction.sent,
    -            ":fee": transaction.fee,
    -            ":height": height,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn update_transaction_details(&self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        let (timestamp, height) = match &transaction.confirmation_time {
    -            Some(confirmation_time) => (
    -                Some(confirmation_time.timestamp),
    -                Some(confirmation_time.height),
    -            ),
    -            None => (None, None),
    -        };
    -
    -        let txid: &[u8] = &transaction.txid;
    -
    -        let mut statement = self.connection.prepare_cached("UPDATE transaction_details SET timestamp=:timestamp, received=:received, sent=:sent, fee=:fee, height=:height WHERE txid=:txid")?;
    -
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":timestamp": timestamp,
    -            ":received": transaction.received,
    -            ":sent": transaction.sent,
    -            ":fee": transaction.fee,
    -            ":height": height,
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn insert_last_derivation_index(&self, keychain: String, value: u32) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "INSERT INTO last_derivation_indices (keychain, value) VALUES (:keychain, :value)",
    -        )?;
    -
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":value": value,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn insert_checksum(&self, keychain: String, checksum: &[u8]) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "INSERT INTO checksums (keychain, checksum) VALUES (:keychain, :checksum)",
    -        )?;
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":checksum": checksum,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn update_last_derivation_index(&self, keychain: String, value: u32) -> Result<(), Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "INSERT INTO last_derivation_indices (keychain, value) VALUES (:keychain, :value) ON CONFLICT(keychain) DO UPDATE SET value=:value WHERE keychain=:keychain",
    -        )?;
    -
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":value": value,
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn update_sync_time(&self, data: SyncTime) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "INSERT INTO sync_time (id, height, timestamp) VALUES (0, :height, :timestamp) ON CONFLICT(id) DO UPDATE SET height=:height, timestamp=:timestamp WHERE id = 0",
    -        )?;
    -
    -        statement.execute(named_params! {
    -            ":height": data.block_time.height,
    -            ":timestamp": data.block_time.timestamp,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn select_script_pubkeys(&self) -> Result<Vec<Script>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT script FROM script_pubkeys")?;
    -        let mut scripts: Vec<Script> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let raw_script: Vec<u8> = row.get(0)?;
    -            scripts.push(raw_script.into());
    -        }
    -
    -        Ok(scripts)
    -    }
    -
    -    fn select_script_pubkeys_by_keychain(&self, keychain: String) -> Result<Vec<Script>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT script FROM script_pubkeys WHERE keychain=:keychain")?;
    -        let mut scripts: Vec<Script> = vec![];
    -        let mut rows = statement.query(named_params! {":keychain": keychain})?;
    -        while let Some(row) = rows.next()? {
    -            let raw_script: Vec<u8> = row.get(0)?;
    -            scripts.push(raw_script.into());
    -        }
    -
    -        Ok(scripts)
    -    }
    -
    -    fn select_script_pubkey_by_path(
    -        &self,
    -        keychain: String,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "SELECT script FROM script_pubkeys WHERE keychain=:keychain AND child=:child",
    -        )?;
    -        let mut rows = statement.query(named_params! {":keychain": keychain,":child": child})?;
    -
    -        match rows.next()? {
    -            Some(row) => {
    -                let script: Vec<u8> = row.get(0)?;
    -                let script: Script = script.into();
    -                Ok(Some(script))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_script_pubkey_by_script(
    -        &self,
    -        script: &[u8],
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT keychain, child FROM script_pubkeys WHERE script=:script")?;
    -        let mut rows = statement.query(named_params! {":script": script})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let keychain: String = row.get(0)?;
    -                let keychain: KeychainKind = serde_json::from_str(&keychain)?;
    -                let child: u32 = row.get(1)?;
    -                Ok(Some((keychain, child)))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT value, keychain, vout, txid, script, is_spent FROM utxos")?;
    -        let mut utxos: Vec<LocalUtxo> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let value = row.get(0)?;
    -            let keychain: String = row.get(1)?;
    -            let vout = row.get(2)?;
    -            let txid: Vec<u8> = row.get(3)?;
    -            let script: Vec<u8> = row.get(4)?;
    -            let is_spent: bool = row.get(5)?;
    -
    -            let keychain: KeychainKind = serde_json::from_str(&keychain)?;
    -
    -            utxos.push(LocalUtxo {
    -                outpoint: OutPoint::new(deserialize(&txid)?, vout),
    -                txout: TxOut {
    -                    value,
    -                    script_pubkey: script.into(),
    -                },
    -                keychain,
    -                is_spent,
    -            })
    -        }
    -
    -        Ok(utxos)
    -    }
    -
    -    fn select_utxo_by_outpoint(&self, txid: &[u8], vout: u32) -> Result<Option<LocalUtxo>, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "SELECT value, keychain, script, is_spent FROM utxos WHERE txid=:txid AND vout=:vout",
    -        )?;
    -        let mut rows = statement.query(named_params! {":txid": txid,":vout": vout})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let value: u64 = row.get(0)?;
    -                let keychain: String = row.get(1)?;
    -                let keychain: KeychainKind = serde_json::from_str(&keychain)?;
    -                let script: Vec<u8> = row.get(2)?;
    -                let script_pubkey: Script = script.into();
    -                let is_spent: bool = row.get(3)?;
    -
    -                Ok(Some(LocalUtxo {
    -                    outpoint: OutPoint::new(deserialize(txid)?, vout),
    -                    txout: TxOut {
    -                        value,
    -                        script_pubkey,
    -                    },
    -                    keychain,
    -                    is_spent,
    -                }))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_transactions(&self) -> Result<Vec<Transaction>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT raw_tx FROM transactions")?;
    -        let mut txs: Vec<Transaction> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let raw_tx: Vec<u8> = row.get(0)?;
    -            let tx: Transaction = deserialize(&raw_tx)?;
    -            txs.push(tx);
    -        }
    -        Ok(txs)
    -    }
    -
    -    fn select_transaction_by_txid(&self, txid: &[u8]) -> Result<Option<Transaction>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT raw_tx FROM transactions WHERE txid=:txid")?;
    -        let mut rows = statement.query(named_params! {":txid": txid})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let raw_tx: Vec<u8> = row.get(0)?;
    -                let tx: Transaction = deserialize(&raw_tx)?;
    -                Ok(Some(tx))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_transaction_details_with_raw(&self) -> Result<Vec<TransactionDetails>, Error> {
    -        let mut statement = self.connection.prepare_cached("SELECT transaction_details.txid, transaction_details.timestamp, transaction_details.received, transaction_details.sent, transaction_details.fee, transaction_details.height, transactions.raw_tx FROM transaction_details, transactions WHERE transaction_details.txid = transactions.txid")?;
    -        let mut transaction_details: Vec<TransactionDetails> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let txid: Vec<u8> = row.get(0)?;
    -            let txid: Txid = deserialize(&txid)?;
    -            let timestamp: Option<u64> = row.get(1)?;
    -            let received: u64 = row.get(2)?;
    -            let sent: u64 = row.get(3)?;
    -            let fee: Option<u64> = row.get(4)?;
    -            let height: Option<u32> = row.get(5)?;
    -            let raw_tx: Option<Vec<u8>> = row.get(6)?;
    -            let tx: Option<Transaction> = match raw_tx {
    -                Some(raw_tx) => {
    -                    let tx: Transaction = deserialize(&raw_tx)?;
    -                    Some(tx)
    -                }
    -                None => None,
    -            };
    -
    -            let confirmation_time = match (height, timestamp) {
    -                (Some(height), Some(timestamp)) => Some(BlockTime { height, timestamp }),
    -                _ => None,
    -            };
    -
    -            transaction_details.push(TransactionDetails {
    -                transaction: tx,
    -                txid,
    -                received,
    -                sent,
    -                fee,
    -                confirmation_time,
    -            });
    -        }
    -        Ok(transaction_details)
    -    }
    -
    -    fn select_transaction_details(&self) -> Result<Vec<TransactionDetails>, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "SELECT txid, timestamp, received, sent, fee, height FROM transaction_details",
    -        )?;
    -        let mut transaction_details: Vec<TransactionDetails> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let txid: Vec<u8> = row.get(0)?;
    -            let txid: Txid = deserialize(&txid)?;
    -            let timestamp: Option<u64> = row.get(1)?;
    -            let received: u64 = row.get(2)?;
    -            let sent: u64 = row.get(3)?;
    -            let fee: Option<u64> = row.get(4)?;
    -            let height: Option<u32> = row.get(5)?;
    -
    -            let confirmation_time = match (height, timestamp) {
    -                (Some(height), Some(timestamp)) => Some(BlockTime { height, timestamp }),
    -                _ => None,
    -            };
    -
    -            transaction_details.push(TransactionDetails {
    -                transaction: None,
    -                txid,
    -                received,
    -                sent,
    -                fee,
    -                confirmation_time,
    -            });
    -        }
    -        Ok(transaction_details)
    -    }
    -
    -    fn select_transaction_details_by_txid(
    -        &self,
    -        txid: &[u8],
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        let mut statement = self.connection.prepare_cached("SELECT transaction_details.timestamp, transaction_details.received, transaction_details.sent, transaction_details.fee, transaction_details.height, transactions.raw_tx FROM transaction_details, transactions WHERE transaction_details.txid=transactions.txid AND transaction_details.txid=:txid")?;
    -        let mut rows = statement.query(named_params! { ":txid": txid })?;
    -
    -        match rows.next()? {
    -            Some(row) => {
    -                let timestamp: Option<u64> = row.get(0)?;
    -                let received: u64 = row.get(1)?;
    -                let sent: u64 = row.get(2)?;
    -                let fee: Option<u64> = row.get(3)?;
    -                let height: Option<u32> = row.get(4)?;
    -
    -                let raw_tx: Option<Vec<u8>> = row.get(5)?;
    -                let tx: Option<Transaction> = match raw_tx {
    -                    Some(raw_tx) => {
    -                        let tx: Transaction = deserialize(&raw_tx)?;
    -                        Some(tx)
    -                    }
    -                    None => None,
    -                };
    -
    -                let confirmation_time = match (height, timestamp) {
    -                    (Some(height), Some(timestamp)) => Some(BlockTime { height, timestamp }),
    -                    _ => None,
    -                };
    -
    -                Ok(Some(TransactionDetails {
    -                    transaction: tx,
    -                    txid: deserialize(txid)?,
    -                    received,
    -                    sent,
    -                    fee,
    -                    confirmation_time,
    -                }))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_last_derivation_index_by_keychain(
    -        &self,
    -        keychain: String,
    -    ) -> Result<Option<u32>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT value FROM last_derivation_indices WHERE keychain=:keychain")?;
    -        let mut rows = statement.query(named_params! {":keychain": keychain})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let value: u32 = row.get(0)?;
    -                Ok(Some(value))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_sync_time(&self) -> Result<Option<SyncTime>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT height, timestamp FROM sync_time WHERE id = 0")?;
    -        let mut rows = statement.query([])?;
    -
    -        if let Some(row) = rows.next()? {
    -            Ok(Some(SyncTime {
    -                block_time: BlockTime {
    -                    height: row.get(0)?,
    -                    timestamp: row.get(1)?,
    -                },
    -            }))
    -        } else {
    -            Ok(None)
    -        }
    -    }
    -
    -    fn select_checksum_by_keychain(&self, keychain: String) -> Result<Option<Vec<u8>>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT checksum FROM checksums WHERE keychain=:keychain")?;
    -        let mut rows = statement.query(named_params! {":keychain": keychain})?;
    -
    -        match rows.next()? {
    -            Some(row) => {
    -                let checksum: Vec<u8> = row.get(0)?;
    -                Ok(Some(checksum))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn delete_script_pubkey_by_path(&self, keychain: String, child: u32) -> Result<(), Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "DELETE FROM script_pubkeys WHERE keychain=:keychain AND child=:child",
    -        )?;
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":child": child
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn delete_script_pubkey_by_script(&self, script: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM script_pubkeys WHERE script=:script")?;
    -        statement.execute(named_params! {
    -            ":script": script
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn delete_utxo_by_outpoint(&self, txid: &[u8], vout: u32) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM utxos WHERE txid=:txid AND vout=:vout")?;
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":vout": vout
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn delete_transaction_by_txid(&self, txid: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM transactions WHERE txid=:txid")?;
    -        statement.execute(named_params! {":txid": txid})?;
    -        Ok(())
    -    }
    -
    -    fn delete_transaction_details_by_txid(&self, txid: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM transaction_details WHERE txid=:txid")?;
    -        statement.execute(named_params! {":txid": txid})?;
    -        Ok(())
    -    }
    -
    -    fn delete_last_derivation_index_by_keychain(&self, keychain: String) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM last_derivation_indices WHERE keychain=:keychain")?;
    -        statement.execute(named_params! {
    -            ":keychain": &keychain
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn delete_sync_time(&self) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM sync_time WHERE id = 0")?;
    -        statement.execute([])?;
    -        Ok(())
    -    }
    -}
    -
    -impl BatchOperations for SqliteDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        self.insert_script_pubkey(keychain, child, script.as_bytes())?;
    -        Ok(())
    -    }
    -
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        self.insert_utxo(
    -            utxo.txout.value,
    -            serde_json::to_string(&utxo.keychain)?,
    -            utxo.outpoint.vout,
    -            &utxo.outpoint.txid,
    -            utxo.txout.script_pubkey.as_bytes(),
    -            utxo.is_spent,
    -        )?;
    -        Ok(())
    -    }
    -
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        match self.select_transaction_by_txid(&transaction.txid())? {
    -            Some(_) => {
    -                self.update_transaction(&transaction.txid(), &serialize(transaction))?;
    -            }
    -            None => {
    -                self.insert_transaction(&transaction.txid(), &serialize(transaction))?;
    -            }
    -        }
    -        Ok(())
    -    }
    -
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        match self.select_transaction_details_by_txid(&transaction.txid)? {
    -            Some(_) => {
    -                self.update_transaction_details(transaction)?;
    -            }
    -            None => {
    -                self.insert_transaction_details(transaction)?;
    -            }
    -        }
    -
    -        if let Some(tx) = &transaction.transaction {
    -            self.set_raw_tx(tx)?;
    -        }
    -
    -        Ok(())
    -    }
    -
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        self.update_last_derivation_index(serde_json::to_string(&keychain)?, value)?;
    -        Ok(())
    -    }
    -
    -    fn set_sync_time(&mut self, ct: SyncTime) -> Result<(), Error> {
    -        self.update_sync_time(ct)?;
    -        Ok(())
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        let script = self.select_script_pubkey_by_path(keychain.clone(), child)?;
    -        match script {
    -            Some(script) => {
    -                self.delete_script_pubkey_by_path(keychain, child)?;
    -                Ok(Some(script))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        match self.select_script_pubkey_by_script(script.as_bytes())? {
    -            Some((keychain, child)) => {
    -                self.delete_script_pubkey_by_script(script.as_bytes())?;
    -                Ok(Some((keychain, child)))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        match self.select_utxo_by_outpoint(&outpoint.txid, outpoint.vout)? {
    -            Some(local_utxo) => {
    -                self.delete_utxo_by_outpoint(&outpoint.txid, outpoint.vout)?;
    -                Ok(Some(local_utxo))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        match self.select_transaction_by_txid(txid)? {
    -            Some(tx) => {
    -                self.delete_transaction_by_txid(txid)?;
    -                Ok(Some(tx))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        match self.select_transaction_details_by_txid(txid)? {
    -            Some(mut transaction_details) => {
    -                self.delete_transaction_details_by_txid(txid)?;
    -
    -                if include_raw {
    -                    self.delete_transaction_by_txid(txid)?;
    -                } else {
    -                    transaction_details.transaction = None;
    -                }
    -                Ok(Some(transaction_details))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        match self.select_last_derivation_index_by_keychain(keychain.clone())? {
    -            Some(value) => {
    -                self.delete_last_derivation_index_by_keychain(keychain)?;
    -
    -                Ok(Some(value))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_sync_time(&mut self) -> Result<Option<SyncTime>, Error> {
    -        match self.select_sync_time()? {
    -            Some(value) => {
    -                self.delete_sync_time()?;
    -
    -                Ok(Some(value))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -}
    -
    -impl Database for SqliteDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -
    -        match self.select_checksum_by_keychain(keychain.clone())? {
    -            Some(checksum) => {
    -                if checksum == bytes.as_ref().to_vec() {
    -                    Ok(())
    -                } else {
    -                    Err(Error::ChecksumMismatch)
    -                }
    -            }
    -            None => {
    -                self.insert_checksum(keychain, bytes.as_ref())?;
    -                Ok(())
    -            }
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        match keychain {
    -            Some(keychain) => {
    -                let keychain = serde_json::to_string(&keychain)?;
    -                self.select_script_pubkeys_by_keychain(keychain)
    -            }
    -            None => self.select_script_pubkeys(),
    -        }
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        self.select_utxos()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        self.select_transactions()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        match include_raw {
    -            true => self.select_transaction_details_with_raw(),
    -            false => self.select_transaction_details(),
    -        }
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        match self.select_script_pubkey_by_path(keychain, child)? {
    -            Some(script) => Ok(Some(script)),
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        match self.select_script_pubkey_by_script(script.as_bytes())? {
    -            Some((keychain, child)) => Ok(Some((keychain, child))),
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        self.select_utxo_by_outpoint(&outpoint.txid, outpoint.vout)
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        match self.select_transaction_by_txid(txid)? {
    -            Some(tx) => Ok(Some(tx)),
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        match self.select_transaction_details_by_txid(txid)? {
    -            Some(mut transaction_details) => {
    -                if !include_raw {
    -                    transaction_details.transaction = None;
    -                }
    -                Ok(Some(transaction_details))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        let value = self.select_last_derivation_index_by_keychain(keychain)?;
    -        Ok(value)
    -    }
    -
    -    fn get_sync_time(&self) -> Result<Option<SyncTime>, Error> {
    -        self.select_sync_time()
    -    }
    -
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let keychain_string = serde_json::to_string(&keychain)?;
    -        match self.get_last_index(keychain)? {
    -            Some(value) => {
    -                self.update_last_derivation_index(keychain_string, value + 1)?;
    -                Ok(value + 1)
    -            }
    -            None => {
    -                self.insert_last_derivation_index(keychain_string, 0)?;
    -                Ok(0)
    -            }
    -        }
    -    }
    -}
    -
    -impl BatchDatabase for SqliteDatabase {
    -    type Batch = SqliteDatabase;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        let db = SqliteDatabase::new(self.path.clone());
    -        db.connection.execute("BEGIN TRANSACTION", []).unwrap();
    -        db
    -    }
    -
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        batch.connection.execute("COMMIT TRANSACTION", [])?;
    -        Ok(())
    -    }
    -}
    -
    -pub fn get_connection<T: AsRef<Path>>(path: &T) -> Result<Connection, Error> {
    -    let mut connection = Connection::open(path)?;
    -    migrate(&mut connection)?;
    -    Ok(connection)
    -}
    -
    -pub fn get_schema_version(conn: &Connection) -> rusqlite::Result<i32> {
    -    let statement = conn.prepare_cached("SELECT version FROM version");
    -    match statement {
    -        Err(rusqlite::Error::SqliteFailure(e, Some(msg))) => {
    -            if msg == "no such table: version" {
    -                Ok(0)
    -            } else {
    -                Err(rusqlite::Error::SqliteFailure(e, Some(msg)))
    -            }
    -        }
    -        Ok(mut stmt) => {
    -            let mut rows = stmt.query([])?;
    -            match rows.next()? {
    -                Some(row) => {
    -                    let version: i32 = row.get(0)?;
    -                    Ok(version)
    -                }
    -                None => Ok(0),
    -            }
    -        }
    -        _ => Ok(0),
    -    }
    -}
    -
    -pub fn set_schema_version(conn: &Connection, version: i32) -> rusqlite::Result<usize> {
    -    conn.execute(
    -        "UPDATE version SET version=:version",
    -        named_params! {":version": version},
    -    )
    -}
    -
    -pub fn migrate(conn: &mut Connection) -> Result<(), Error> {
    -    let version = get_schema_version(conn)?;
    -    let stmts = &MIGRATIONS[(version as usize)..];
    -
    -    // begin transaction, all migration statements and new schema version commit or rollback
    -    let tx = conn.transaction()?;
    -
    -    // execute every statement and return `Some` new schema version
    -    // if execution fails, return `Error::Rusqlite`
    -    // if no statements executed returns `None`
    -    let new_version = stmts
    -        .iter()
    -        .enumerate()
    -        .map(|version_stmt| {
    -            log::info!(
    -                "executing db migration {}: `{}`",
    -                version + version_stmt.0 as i32 + 1,
    -                version_stmt.1
    -            );
    -            tx.execute(version_stmt.1, [])
    -                // map result value to next migration version
    -                .map(|_| version_stmt.0 as i32 + version + 1)
    -        })
    -        .last()
    -        .transpose()?;
    -
    -    // if `Some` new statement version, set new schema version
    -    if let Some(version) = new_version {
    -        set_schema_version(&tx, version)?;
    -    } else {
    -        log::info!("db up to date, no migration needed");
    -    }
    -
    -    // commit transaction
    -    tx.commit()?;
    -    Ok(())
    -}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use crate::database::SqliteDatabase;
    -    use std::time::{SystemTime, UNIX_EPOCH};
    -
    -    fn get_database() -> SqliteDatabase {
    -        let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    -        let mut dir = std::env::temp_dir();
    -        dir.push(format!("bdk_{}", time.as_nanos()));
    -        SqliteDatabase::new(String::from(dir.to_str().unwrap()))
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_database());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_database());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_database());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_database());
    -    }
    -
    -    #[test]
    -    fn test_sync_time() {
    -        crate::database::test::test_sync_time(get_database());
    -    }
    -
    -    #[test]
    -    fn test_txs() {
    -        crate::database::test::test_list_transaction(get_database());
    -    }
    -
    -    #[test]
    -    fn test_iter_raw_txs() {
    -        crate::database::test::test_iter_raw_txs(get_database());
    -    }
    -
    -    #[test]
    -    fn test_del_path_from_script_pubkey() {
    -        crate::database::test::test_del_path_from_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkeys() {
    -        crate::database::test::test_iter_script_pubkeys(get_database());
    -    }
    -
    -    #[test]
    -    fn test_del_utxo() {
    -        crate::database::test::test_del_utxo(get_database());
    -    }
    -
    -    #[test]
    -    fn test_del_raw_tx() {
    -        crate::database::test::test_del_raw_tx(get_database());
    -    }
    -
    -    #[test]
    -    fn test_del_tx() {
    -        crate::database::test::test_del_tx(get_database());
    -    }
    -
    -    #[test]
    -    fn test_del_last_index() {
    -        crate::database::test::test_del_last_index(get_database());
    -    }
    -
    -    #[test]
    -    fn test_check_descriptor_checksum() {
    -        crate::database::test::test_check_descriptor_checksum(get_database());
    -    }
    -
    -    // Issue 801: https://github.com/bitcoindevkit/bdk/issues/801
    -    #[test]
    -    fn test_unique_spks() {
    -        use crate::bitcoin::hashes::hex::FromHex;
    -        use crate::database::*;
    -
    -        let mut db = get_database();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        for _ in 0..100 {
    -            db.set_script_pubkey(&script, keychain, path).unwrap();
    -        }
    -
    -        let mut statement = db
    -            .connection
    -            .prepare_cached(
    -                "select keychain,child,count(child) from script_pubkeys group by keychain,child;",
    -            )
    -            .unwrap();
    -        let mut rows = statement.query([]).unwrap();
    -        while let Some(row) = rows.next().unwrap() {
    -            let keychain: String = row.get(0).unwrap();
    -            let child: u32 = row.get(1).unwrap();
    -            let count: usize = row.get(2).unwrap();
    -
    -            assert_eq!(
    -                count, 1,
    -                "keychain={}, child={}, count={}",
    -                keychain, child, count
    -            );
    -        }
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html index 3ea964b7c1..680af67c99 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html @@ -1,5 +1,4 @@ -checksum.rs - source
    1
    +checksum.rs - source
    1
     2
     3
     4
    @@ -180,6 +179,7 @@
     179
     180
     181
    +182
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -197,6 +197,7 @@
     //! checksum of a descriptor
     
     use crate::descriptor::DescriptorError;
    +use alloc::string::String;
     
     const INPUT_CHARSET: &[u8] = b"0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
     const CHECKSUM_CHARSET: &[u8] = b"qpzry9x8gf2tvdw0s3jn54khce6mua7l";
    @@ -352,7 +353,7 @@
     
         #[test]
         fn test_calc_checksum_invalid_character() {
    -        let sparkle_heart = unsafe { std::str::from_utf8_unchecked(&[240, 159, 146, 150]) };
    +        let sparkle_heart = unsafe { core::str::from_utf8_unchecked(&[240, 159, 146, 150]) };
             let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart);
     
             assert_matches!(
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html
    index c8e46e4600..b04b905081 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html
    @@ -1,5 +1,4 @@
    -dsl.rs - source
    1
    +dsl.rs - source
    1
     2
     3
     4
    @@ -1218,6 +1217,9 @@
     1217
     1218
     1219
    +1220
    +1221
    +1222
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -1243,7 +1245,7 @@
         };
     
         ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti $( $inner:tt )* ) => {{
    -        use std::marker::PhantomData;
    +        use core::marker::PhantomData;
     
             use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
             use $crate::miniscript::$ctx;
    @@ -1255,7 +1257,7 @@
             $crate::impl_sortedmulti!(build_desc, sortedmulti $( $inner )*)
         }};
         ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti_vec $( $inner:tt )* ) => {{
    -        use std::marker::PhantomData;
    +        use core::marker::PhantomData;
     
             use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
             use $crate::miniscript::$ctx;
    @@ -1423,8 +1425,8 @@
                     a_keymap.extend(b_keymap.into_iter());
     
                     let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
    -                    std::sync::Arc::new(a_minisc),
    -                    std::sync::Arc::new(b_minisc),
    +                    $crate::alloc::sync::Arc::new(a_minisc),
    +                    $crate::alloc::sync::Arc::new(b_minisc),
                     ))?;
     
                     minisc.check_miniscript()?;
    @@ -1454,9 +1456,9 @@
                     let networks = $crate::keys::merge_networks(&networks, &c_networks);
     
                     let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
    -                    std::sync::Arc::new(a_minisc),
    -                    std::sync::Arc::new(b_minisc),
    -                    std::sync::Arc::new(c_minisc),
    +                    $crate::alloc::sync::Arc::new(a_minisc),
    +                    $crate::alloc::sync::Arc::new(b_minisc),
    +                    $crate::alloc::sync::Arc::new(c_minisc),
                     ))?;
     
                     minisc.check_miniscript()?;
    @@ -1483,7 +1485,7 @@
                 )*
             ];
     
    -        keys.into_iter().collect::<Result<Vec<_>, _>>()
    +        keys.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
                 .map_err($crate::descriptor::DescriptorError::Key)
                 .and_then(|keys| $crate::keys::make_sortedmulti($thresh, keys, $build_desc, &secp))
         });
    @@ -1494,7 +1496,7 @@
     #[macro_export]
     macro_rules! parse_tap_tree {
         ( @merge $tree_a:expr, $tree_b:expr) => {{
    -        use std::sync::Arc;
    +        use $crate::alloc::sync::Arc;
             use $crate::miniscript::descriptor::TapTree;
     
             $tree_a
    @@ -1538,7 +1540,7 @@
     
         // Single leaf
         ( $op:ident ( $( $minisc:tt )* ) ) => {{
    -        use std::sync::Arc;
    +        use $crate::alloc::sync::Arc;
             use $crate::miniscript::descriptor::TapTree;
     
             $crate::fragment!( $op ( $( $minisc )* ) )
    @@ -1557,7 +1559,7 @@
                 .and_then(|(minisc, keymap, networks)| {
                     let minisc = $crate::miniscript::Miniscript::from_ast(
                         $crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
    -                        std::sync::Arc::new(minisc),
    +                        $crate::alloc::sync::Arc::new(minisc),
                         ),
                     )?;
     
    @@ -1594,8 +1596,8 @@
             $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
                 $crate::impl_leaf_opcode_value_two!(
                     AndV,
    -                std::sync::Arc::new(a_minisc),
    -                std::sync::Arc::new($crate::fragment!(true).unwrap().0)
    +                $crate::alloc::sync::Arc::new(a_minisc),
    +                $crate::alloc::sync::Arc::new($crate::fragment!(true).unwrap().0)
                 )
                 .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
             })
    @@ -1604,8 +1606,8 @@
             $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
                 $crate::impl_leaf_opcode_value_two!(
                     OrI,
    -                std::sync::Arc::new($crate::fragment!(false).unwrap().0),
    -                std::sync::Arc::new(a_minisc)
    +                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0),
    +                $crate::alloc::sync::Arc::new(a_minisc)
                 )
                 .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
             })
    @@ -1614,8 +1616,8 @@
             $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
                 $crate::impl_leaf_opcode_value_two!(
                     OrI,
    -                std::sync::Arc::new(a_minisc),
    -                std::sync::Arc::new($crate::fragment!(false).unwrap().0)
    +                $crate::alloc::sync::Arc::new(a_minisc),
    +                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0)
                 )
                 .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
             })
    @@ -1715,6 +1717,8 @@
     /// let (descriptor, key_map, networks) = bdk::descriptor!(wpkh(my_key))?;
     /// # Ok::<(), Box<dyn std::error::Error>>(())
     /// ```
    +///
    +/// [`Vec`]: alloc::vec::Vec
     #[macro_export]
     macro_rules! descriptor {
         ( bare ( $( $minisc:tt )* ) ) => ({
    @@ -1819,7 +1823,7 @@
                 )*
             ];
     
    -        keys.into_iter().collect::<Result<Vec<_>, _>>()
    +        keys.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
                 .map_err($crate::descriptor::DescriptorError::Key)
         }};
     }
    @@ -1964,8 +1968,8 @@
         ( thresh_vec ( $thresh:expr, $items:expr ) ) => ({
             use $crate::miniscript::descriptor::KeyMap;
     
    -        let (items, key_maps_networks): (Vec<_>, Vec<_>) = $items.into_iter().map(|(a, b, c)| (a, (b, c))).unzip();
    -        let items = items.into_iter().map(std::sync::Arc::new).collect();
    +        let (items, key_maps_networks): ($crate::alloc::vec::Vec<_>, $crate::alloc::vec::Vec<_>) = $items.into_iter().map(|(a, b, c)| (a, (b, c))).unzip();
    +        let items = items.into_iter().map($crate::alloc::sync::Arc::new).collect();
     
             let (key_maps, valid_networks) = key_maps_networks.into_iter().fold((KeyMap::default(), $crate::keys::any_network()), |(mut keys_acc, net_acc), (key, net)| {
                 keys_acc.extend(key.into_iter());
    @@ -1980,7 +1984,7 @@
         ( thresh ( $thresh:expr, $( $inner:tt )* ) ) => ({
             let items = $crate::fragment_internal!( @v $( $inner )* );
     
    -        items.into_iter().collect::<Result<Vec<_>, _>>()
    +        items.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
                 .and_then(|items| $crate::fragment!(thresh_vec($thresh, items)))
         });
         ( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
    @@ -2013,12 +2017,13 @@
     
     #[cfg(test)]
     mod test {
    +    use alloc::string::ToString;
         use bitcoin::hashes::hex::ToHex;
         use bitcoin::secp256k1::Secp256k1;
         use miniscript::descriptor::{DescriptorPublicKey, KeyMap};
         use miniscript::{Descriptor, Legacy, Segwitv0};
     
    -    use std::str::FromStr;
    +    use core::str::FromStr;
     
         use crate::descriptor::{DescriptorError, DescriptorMeta};
         use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html
    index 952313e5f3..08400732a5 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html
    @@ -1,5 +1,4 @@
    -error.rs - source
    1
    +error.rs - source
    1
     2
     3
     4
    @@ -85,6 +84,7 @@
     84
     85
     86
    +87
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -163,7 +163,8 @@
         }
     }
     
    -impl std::error::Error for Error {}
    +#[cfg(feature = "std")]
    +impl std::error::Error for Error {}
     
     impl_error!(bitcoin::util::bip32::Error, Bip32);
     impl_error!(bitcoin::util::base58::Error, Base58);
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html
    index 7f7e081ef5..3c1c964b6e 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html
    @@ -1,5 +1,4 @@
    -mod.rs - source
    1
    +mod.rs - source
    1
     2
     3
     4
    @@ -872,6 +871,9 @@
     871
     872
     873
    +874
    +875
    +876
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -888,7 +890,9 @@
     //! This module contains generic utilities to work with descriptors, plus some re-exported types
     //! from [`miniscript`].
     
    -use std::collections::BTreeMap;
    +use crate::collections::BTreeMap;
    +use alloc::string::String;
    +use alloc::vec::Vec;
     
     use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint, KeySource};
     use bitcoin::util::{psbt, taproot};
    @@ -1227,27 +1231,27 @@
     pub(crate) trait DescriptorMeta {
         fn is_witness(&self) -> bool;
         fn is_taproot(&self) -> bool;
    -    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError>;
    -    fn derive_from_hd_keypaths<'s>(
    +    fn get_extended_keys(&self) -> Vec<DescriptorXKey<ExtendedPubKey>>;
    +    fn derive_from_hd_keypaths(
             &self,
             hd_keypaths: &HdKeyPaths,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor>;
    -    fn derive_from_tap_key_origins<'s>(
    +    fn derive_from_tap_key_origins(
             &self,
             tap_key_origins: &TapKeyOrigins,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor>;
    -    fn derive_from_psbt_key_origins<'s>(
    +    fn derive_from_psbt_key_origins(
             &self,
             key_origins: BTreeMap<Fingerprint, (&DerivationPath, SinglePubKey)>,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor>;
    -    fn derive_from_psbt_input<'s>(
    +    fn derive_from_psbt_input(
             &self,
             psbt_input: &psbt::Input,
             utxo: Option<TxOut>,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor>;
     }
     
    @@ -1268,7 +1272,7 @@
             self.desc_type() == DescriptorType::Tr
         }
     
    -    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError> {
    +    fn get_extended_keys(&self) -> Vec<DescriptorXKey<ExtendedPubKey>> {
             let mut answer = Vec::new();
     
             self.for_each_key(|pk| {
    @@ -1279,13 +1283,13 @@
                 true
             });
     
    -        Ok(answer)
    +        answer
         }
     
    -    fn derive_from_psbt_key_origins<'s>(
    +    fn derive_from_psbt_key_origins(
             &self,
             key_origins: BTreeMap<Fingerprint, (&DerivationPath, SinglePubKey)>,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor> {
             // Ensure that deriving `xpub` with `path` yields `expected`
             let verify_key = |xpub: &DescriptorXKey<ExtendedPubKey>,
    @@ -1369,10 +1373,10 @@
             path_found.map(|path| self.at_derivation_index(path))
         }
     
    -    fn derive_from_hd_keypaths<'s>(
    +    fn derive_from_hd_keypaths(
             &self,
             hd_keypaths: &HdKeyPaths,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor> {
             // "Convert" an hd_keypaths map to the format required by `derive_from_psbt_key_origins`
             let key_origins = hd_keypaths
    @@ -1387,10 +1391,10 @@
             self.derive_from_psbt_key_origins(key_origins, secp)
         }
     
    -    fn derive_from_tap_key_origins<'s>(
    +    fn derive_from_tap_key_origins(
             &self,
             tap_key_origins: &TapKeyOrigins,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor> {
             // "Convert" a tap_key_origins map to the format required by `derive_from_psbt_key_origins`
             let key_origins = tap_key_origins
    @@ -1400,11 +1404,11 @@
             self.derive_from_psbt_key_origins(key_origins, secp)
         }
     
    -    fn derive_from_psbt_input<'s>(
    +    fn derive_from_psbt_input(
             &self,
             psbt_input: &psbt::Input,
             utxo: Option<TxOut>,
    -        secp: &'s SecpCtx,
    +        secp: &SecpCtx,
         ) -> Option<DerivedDescriptor> {
             if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.bip32_derivation, secp) {
                 return Some(derived);
    @@ -1453,7 +1457,8 @@
     
     #[cfg(test)]
     mod test {
    -    use std::str::FromStr;
    +    use alloc::string::ToString;
    +    use core::str::FromStr;
     
         use assert_matches::assert_matches;
         use bitcoin::consensus::encode::deserialize;
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html
    index c96ce826cb..1fc8ad9036 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html
    @@ -1,5 +1,4 @@
    -policy.rs - source
    1
    +policy.rs - source
    1
     2
     3
     4
    @@ -1882,6 +1881,9 @@
     1881
     1882
     1883
    +1884
    +1885
    +1886
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -1916,13 +1918,15 @@
     //!
     //! let signers = Arc::new(SignersContainer::build(key_map, &extended_desc, &secp));
     //! let policy = extended_desc.extract_policy(&signers, BuildSatisfaction::None, &secp)?;
    -//! println!("policy: {}", serde_json::to_string(&policy)?);
    +//! println!("policy: {}", serde_json::to_string(&policy).unwrap());
     //! # Ok::<(), bdk::Error>(())
     //! ```
     
    -use std::cmp::max;
    -use std::collections::{BTreeMap, HashSet, VecDeque};
    -use std::fmt;
    +use crate::collections::{BTreeMap, HashSet, VecDeque};
    +use alloc::string::String;
    +use alloc::vec::Vec;
    +use core::cmp::max;
    +use core::fmt;
     
     use serde::ser::SerializeMap;
     use serde::{Serialize, Serializer};
    @@ -2407,7 +2411,8 @@
         }
     }
     
    -impl std::error::Error for PolicyError {}
    +#[cfg(feature = "std")]
    +impl std::error::Error for PolicyError {}
     
     impl Policy {
         fn new(item: SatisfiableItem) -> Self {
    @@ -3030,12 +3035,12 @@
         use crate::descriptor::policy::SatisfiableItem::{EcdsaSignature, Multisig, Thresh};
         use crate::keys::{DescriptorKey, IntoDescriptorKey};
         use crate::wallet::signer::SignersContainer;
    +    use alloc::{string::ToString, sync::Arc};
         use assert_matches::assert_matches;
         use bitcoin::secp256k1::Secp256k1;
         use bitcoin::util::bip32;
         use bitcoin::Network;
    -    use std::str::FromStr;
    -    use std::sync::Arc;
    +    use core::str::FromStr;
     
         const TPRV0_STR:&str = "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf";
         const TPRV1_STR:&str = "tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N";
    @@ -3328,12 +3333,12 @@
                 .into_wallet_descriptor(&secp, Network::Testnet)
                 .unwrap();
             let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
    -        let policy = wallet_desc
    +        let _policy = wallet_desc
                 .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
                 .unwrap()
                 .unwrap();
    -        println!("desc policy = {:?}", policy); // TODO remove
    -                                                // TODO how should this fail with mixed timelocks?
    +        // println!("desc policy = {:?}", policy); // TODO remove
    +        // TODO how should this fail with mixed timelocks?
         }
     
         // - multiple timelocks of the same type should be correctly merged together
    @@ -3353,12 +3358,12 @@
                 .into_wallet_descriptor(&secp, Network::Testnet)
                 .unwrap();
             let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
    -        let policy = wallet_desc
    +        let _policy = wallet_desc
                 .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
                 .unwrap()
                 .unwrap();
    -        println!("desc policy = {:?}", policy); // TODO remove
    -                                                // TODO how should this merge timelocks?
    +        // println!("desc policy = {:?}", policy); // TODO remove
    +        // TODO how should this merge timelocks?
             let (prvkey1, _pubkey1, _fingerprint1) = setup_keys(TPRV0_STR, PATH, &secp);
             let locktime_seconds0 = 500000100;
             let locktime_seconds1 = 500000200;
    @@ -3371,12 +3376,12 @@
                 .into_wallet_descriptor(&secp, Network::Testnet)
                 .unwrap();
             let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
    -        let policy = wallet_desc
    +        let _policy = wallet_desc
                 .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
                 .unwrap()
                 .unwrap();
     
    -        println!("desc policy = {:?}", policy); // TODO remove
    +        // println!("desc policy = {:?}", policy); // TODO remove
     
             // TODO how should this merge timelocks?
         }
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html
    index 0b1bc68c94..57d8ee1b9b 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html
    @@ -1,5 +1,4 @@
    -template.rs - source
    1
    +template.rs - source
    1
     2
     3
     4
    @@ -750,35 +749,6 @@
     749
     750
     751
    -752
    -753
    -754
    -755
    -756
    -757
    -758
    -759
    -760
    -761
    -762
    -763
    -764
    -765
    -766
    -767
    -768
    -769
    -770
    -771
    -772
    -773
    -774
    -775
    -776
    -777
    -778
    -779
    -780
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -854,22 +824,16 @@
     ///
     /// ```
     /// # use bdk::bitcoin::{PrivateKey, Network};
    -/// # use bdk::{Wallet};
    -/// # use bdk::database::MemoryDatabase;
    +/// # use bdk::Wallet;
     /// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::P2Pkh;
     ///
     /// let key =
     ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet = Wallet::new(
    -///     P2Pkh(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    +/// let mut wallet = Wallet::new_no_persist(P2Pkh(key), None, Network::Testnet)?;
     ///
     /// assert_eq!(
    -///     wallet.get_address(New)?.to_string(),
    +///     wallet.get_address(New).to_string(),
     ///     "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
     /// );
     /// # Ok::<_, Box<dyn std::error::Error>>(())
    @@ -888,22 +852,16 @@
     ///
     /// ```
     /// # use bdk::bitcoin::{PrivateKey, Network};
    -/// # use bdk::{Wallet};
    -/// # use bdk::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    +/// # use bdk::Wallet;
     /// use bdk::template::P2Wpkh_P2Sh;
    +/// use bdk::wallet::AddressIndex;
     ///
     /// let key =
     ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet = Wallet::new(
    -///     P2Wpkh_P2Sh(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    +/// let mut wallet = Wallet::new_no_persist(P2Wpkh_P2Sh(key), None, Network::Testnet)?;
     ///
     /// assert_eq!(
    -///     wallet.get_address(New)?.to_string(),
    +///     wallet.get_address(AddressIndex::New).to_string(),
     ///     "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
     /// );
     /// # Ok::<_, Box<dyn std::error::Error>>(())
    @@ -924,21 +882,15 @@
     /// ```
     /// # use bdk::bitcoin::{PrivateKey, Network};
     /// # use bdk::{Wallet};
    -/// # use bdk::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::P2Wpkh;
    +/// use bdk::wallet::AddressIndex::New;
     ///
     /// let key =
     ///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet = Wallet::new(
    -///     P2Wpkh(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    +/// let mut wallet = Wallet::new_no_persist(P2Wpkh(key), None, Network::Testnet)?;
     ///
     /// assert_eq!(
    -///     wallet.get_address(New)?.to_string(),
    +///     wallet.get_address(New).to_string(),
     ///     "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
     /// );
     /// # Ok::<_, Box<dyn std::error::Error>>(())
    @@ -963,20 +915,18 @@
     /// # use std::str::FromStr;
     /// # use bdk::bitcoin::{PrivateKey, Network};
     /// # use bdk::{Wallet,  KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
     /// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::Bip44;
     ///
     /// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet = Wallet::new(
    +/// let mut wallet = Wallet::new_no_persist(
     ///     Bip44(key.clone(), KeychainKind::External),
     ///     Some(Bip44(key, KeychainKind::Internal)),
     ///     Network::Testnet,
    -///     MemoryDatabase::default()
     /// )?;
     ///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "mmogjc7HJEZkrLqyQYqJmxUqFaC7i4uf89");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDCuorCpzvYS2LCD75BR46KHE8GdDeg1wsAgNZeNr6DaB5gQK1o14uErKwKLuFmeemkQ6N2m3rNgvctdJLyr7nwu2yia7413Hhg8WWE44cgT/0/*)#5wrnv0xt");
    +/// assert_eq!(wallet.get_address(New).to_string(), "mmogjc7HJEZkrLqyQYqJmxUqFaC7i4uf89");
    +/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDCuorCpzvYS2LCD75BR46KHE8GdDeg1wsAgNZeNr6DaB5gQK1o14uErKwKLuFmeemkQ6N2m3rNgvctdJLyr7nwu2yia7413Hhg8WWE44cgT/0/*)#5wrnv0xt");
     /// # Ok::<_, Box<dyn std::error::Error>>(())
     /// ```
     pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
    @@ -1002,21 +952,19 @@
     /// # use std::str::FromStr;
     /// # use bdk::bitcoin::{PrivateKey, Network};
     /// # use bdk::{Wallet,  KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
     /// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::Bip44Public;
     ///
     /// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
     /// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet = Wallet::new(
    +/// let mut wallet = Wallet::new_no_persist(
     ///     Bip44Public(key.clone(), fingerprint, KeychainKind::External),
     ///     Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
     ///     Network::Testnet,
    -///     MemoryDatabase::default()
     /// )?;
     ///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#cfhumdqz");
    +/// assert_eq!(wallet.get_address(New).to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    +/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "pkh([c55b303f/44'/1'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#cfhumdqz");
     /// # Ok::<_, Box<dyn std::error::Error>>(())
     /// ```
     pub struct Bip44Public<K: DerivableKey<Legacy>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
    @@ -1042,20 +990,18 @@
     /// # use std::str::FromStr;
     /// # use bdk::bitcoin::{PrivateKey, Network};
     /// # use bdk::{Wallet,  KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
     /// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::Bip49;
     ///
     /// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet = Wallet::new(
    +/// let mut wallet = Wallet::new_no_persist(
     ///     Bip49(key.clone(), KeychainKind::External),
     ///     Some(Bip49(key, KeychainKind::Internal)),
     ///     Network::Testnet,
    -///     MemoryDatabase::default()
     /// )?;
     ///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "2N4zkWAoGdUv4NXhSsU8DvS5MB36T8nKHEB");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDDYr4kdnZgjjShzYNjZUZXUUtpXaofdkMaipyS8ThEh45qFmhT4hKYways7UXmg6V7het1QiFo9kf4kYUXyDvV4rHEyvSpys9pjCB3pukxi/0/*))#s9vxlc8e");
    +/// assert_eq!(wallet.get_address(New).to_string(), "2N4zkWAoGdUv4NXhSsU8DvS5MB36T8nKHEB");
    +/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDDYr4kdnZgjjShzYNjZUZXUUtpXaofdkMaipyS8ThEh45qFmhT4hKYways7UXmg6V7het1QiFo9kf4kYUXyDvV4rHEyvSpys9pjCB3pukxi/0/*))#s9vxlc8e");
     /// # Ok::<_, Box<dyn std::error::Error>>(())
     /// ```
     pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    @@ -1081,21 +1027,19 @@
     /// # use std::str::FromStr;
     /// # use bdk::bitcoin::{PrivateKey, Network};
     /// # use bdk::{Wallet,  KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
     /// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::Bip49Public;
     ///
     /// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
     /// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet = Wallet::new(
    +/// let mut wallet = Wallet::new_no_persist(
     ///     Bip49Public(key.clone(), fingerprint, KeychainKind::External),
     ///     Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
     ///     Network::Testnet,
    -///     MemoryDatabase::default()
     /// )?;
     ///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#3tka9g0q");
    +/// assert_eq!(wallet.get_address(New).to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    +/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "sh(wpkh([c55b303f/49'/1'/0']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#3tka9g0q");
     /// # Ok::<_, Box<dyn std::error::Error>>(())
     /// ```
     pub struct Bip49Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
    @@ -1121,20 +1065,18 @@
     /// # use std::str::FromStr;
     /// # use bdk::bitcoin::{PrivateKey, Network};
     /// # use bdk::{Wallet,  KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
     /// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::Bip84;
     ///
     /// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet = Wallet::new(
    +/// let mut wallet = Wallet::new_no_persist(
     ///     Bip84(key.clone(), KeychainKind::External),
     ///     Some(Bip84(key, KeychainKind::Internal)),
     ///     Network::Testnet,
    -///     MemoryDatabase::default()
     /// )?;
     ///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "tb1qhl85z42h7r4su5u37rvvw0gk8j2t3n9y7zsg4n");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDDc5mum24DekpNw92t6fHGp8Gr2JjF9J7i4TZBtN6Vp8xpAULG5CFaKsfugWa5imhrQQUZKXe261asP5koDHo5bs3qNTmf3U3o4v9SaB8gg/0/*)#6kfecsmr");
    +/// assert_eq!(wallet.get_address(New).to_string(), "tb1qhl85z42h7r4su5u37rvvw0gk8j2t3n9y7zsg4n");
    +/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDDc5mum24DekpNw92t6fHGp8Gr2JjF9J7i4TZBtN6Vp8xpAULG5CFaKsfugWa5imhrQQUZKXe261asP5koDHo5bs3qNTmf3U3o4v9SaB8gg/0/*)#6kfecsmr");
     /// # Ok::<_, Box<dyn std::error::Error>>(())
     /// ```
     pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    @@ -1160,21 +1102,19 @@
     /// # use std::str::FromStr;
     /// # use bdk::bitcoin::{PrivateKey, Network};
     /// # use bdk::{Wallet,  KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
     /// # use bdk::wallet::AddressIndex::New;
     /// use bdk::template::Bip84Public;
     ///
     /// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
     /// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet = Wallet::new(
    +/// let mut wallet = Wallet::new_no_persist(
     ///     Bip84Public(key.clone(), fingerprint, KeychainKind::External),
     ///     Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
     ///     Network::Testnet,
    -///     MemoryDatabase::default()
     /// )?;
     ///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#dhu402yv");
    +/// assert_eq!(wallet.get_address(New).to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    +/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "wpkh([c55b303f/84'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#dhu402yv");
     /// # Ok::<_, Box<dyn std::error::Error>>(())
     /// ```
     pub struct Bip84Public<K: DerivableKey<Segwitv0>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
    @@ -1199,7 +1139,7 @@
                     keychain: KeychainKind,
                     network: Network,
                 ) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
    -                let mut derivation_path = Vec::with_capacity(4);
    +                let mut derivation_path = alloc::vec::Vec::with_capacity(4);
                     derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
     
                     match network {
    @@ -1259,7 +1199,8 @@
     mod test {
         // test existing descriptor templates, make sure they are expanded to the right descriptors
     
    -    use std::str::FromStr;
    +    use alloc::{string::ToString, vec::Vec};
    +    use core::str::FromStr;
     
         use super::*;
         use crate::descriptor::{DescriptorError, DescriptorMeta};
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html
    index f0f85371dc..0613c93a87 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html
    @@ -1,5 +1,4 @@
    -error.rs - source
    1
    +error.rs - source
    1
     2
     3
     4
    @@ -198,155 +197,6 @@
     197
     198
     199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -358,21 +208,17 @@
     // You may not use this file except in accordance with one or both of these
     // licenses.
     
    -use std::fmt;
    -
    -use crate::bitcoin::Network;
    +use crate::bitcoin::Network;
     use crate::{descriptor, wallet};
    +use alloc::{string::String, vec::Vec};
     use bitcoin::{OutPoint, Txid};
    +use core::fmt;
     
     /// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
     #[derive(Debug)]
     pub enum Error {
    -    /// Wrong number of bytes found when trying to convert to u32
    -    InvalidU32Bytes(Vec<u8>),
         /// Generic error
         Generic(String),
    -    /// This error is thrown when trying to convert Bare and Public key script to address
    -    ScriptDoesntHaveAddressForm,
         /// Cannot build a tx without recipients
         NoRecipients,
         /// `manually_selected_only` option is selected but no utxo has been passed
    @@ -428,74 +274,18 @@
         InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
         /// Signing error
         Signer(crate::wallet::signer::SignerError),
    -    /// Invalid network
    -    InvalidNetwork {
    -        /// requested network, for example what is given as bdk-cli option
    -        requested: Network,
    -        /// found network, for example the network of the bitcoin node
    -        found: Network,
    -    },
    -    #[cfg(feature = "verify")]
    -    /// Transaction verification error
    -    Verification(crate::wallet::verify::VerifyError),
    -
    -    /// Progress value must be between `0.0` (included) and `100.0` (included)
    -    InvalidProgressValue(f32),
    -    /// Progress update error (maybe the channel has been closed)
    -    ProgressUpdateError,
         /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
         InvalidOutpoint(OutPoint),
    -
         /// Error related to the parsing and usage of descriptors
         Descriptor(crate::descriptor::error::Error),
    -    /// Encoding error
    -    Encode(bitcoin::consensus::encode::Error),
         /// Miniscript error
         Miniscript(miniscript::Error),
         /// Miniscript PSBT error
         MiniscriptPsbt(MiniscriptPsbtError),
         /// BIP32 error
         Bip32(bitcoin::util::bip32::Error),
    -    /// A secp256k1 error
    -    Secp256k1(bitcoin::secp256k1::Error),
    -    /// Error serializing or deserializing JSON data
    -    Json(serde_json::Error),
    -    /// Hex decoding error
    -    Hex(bitcoin::hashes::hex::Error),
         /// Partially signed bitcoin transaction error
         Psbt(bitcoin::util::psbt::Error),
    -    /// Partially signed bitcoin transaction parse error
    -    PsbtParse(bitcoin::util::psbt::PsbtParseError),
    -
    -    //KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
    -    //MissingInputUTXO(usize),
    -    //InvalidAddressNetwork(Address),
    -    //DifferentTransactions,
    -    //DifferentDescriptorStructure,
    -    //Uncapable(crate::blockchain::Capability),
    -    //MissingCachedAddresses,
    -    /// [`crate::blockchain::WalletSync`] sync attempt failed due to missing scripts in cache which
    -    /// are needed to satisfy `stop_gap`.
    -    MissingCachedScripts(MissingCachedScripts),
    -
    -    #[cfg(feature = "electrum")]
    -    /// Electrum client error
    -    Electrum(electrum_client::Error),
    -    #[cfg(feature = "esplora")]
    -    /// Esplora client error
    -    Esplora(Box<crate::blockchain::esplora::EsploraError>),
    -    #[cfg(feature = "compact_filters")]
    -    /// Compact filters client error)
    -    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
    -    #[cfg(feature = "key-value-db")]
    -    /// Sled database error
    -    Sled(sled::Error),
    -    #[cfg(feature = "rpc")]
    -    /// Rpc client error
    -    Rpc(bitcoincore_rpc::Error),
    -    #[cfg(feature = "sqlite")]
    -    /// Rusqlite client error
    -    Rusqlite(rusqlite::Error),
     }
     
     /// Errors returned by miniscript when updating inconsistent PSBTs
    @@ -518,25 +308,10 @@
     
     impl std::error::Error for MiniscriptPsbtError {}
     
    -/// Represents the last failed [`crate::blockchain::WalletSync`] sync attempt in which we were short
    -/// on cached `scriptPubKey`s.
    -#[derive(Debug)]
    -pub struct MissingCachedScripts {
    -    /// Number of scripts in which txs were requested during last request.
    -    pub last_count: usize,
    -    /// Minimum number of scripts to cache more of in order to satisfy `stop_gap`.
    -    pub missing_count: usize,
    -}
    -
     impl fmt::Display for Error {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             match self {
    -            Self::InvalidU32Bytes(_) => write!(
    -                f,
    -                "Wrong number of bytes found when trying to convert to u32"
    -            ),
                 Self::Generic(err) => write!(f, "Generic error: {}", err),
    -            Self::ScriptDoesntHaveAddressForm => write!(f, "Script doesn't have address form"),
                 Self::NoRecipients => write!(f, "Cannot build tx without recipients"),
                 Self::NoUtxosSelected => write!(f, "No UTXO selected"),
                 Self::OutputBelowDustLimit(limit) => {
    @@ -572,62 +347,29 @@
                 }
                 Self::InvalidPolicyPathError(err) => write!(f, "Invalid policy path: {}", err),
                 Self::Signer(err) => write!(f, "Signer error: {}", err),
    -            Self::InvalidNetwork { requested, found } => write!(
    -                f,
    -                "Invalid network: requested {} but found {}",
    -                requested, found
    -            ),
    -            #[cfg(feature = "verify")]
    -            Self::Verification(err) => write!(f, "Transaction verification error: {}", err),
    -            Self::InvalidProgressValue(progress) => {
    -                write!(f, "Invalid progress value: {}", progress)
    -            }
    -            Self::ProgressUpdateError => write!(
    -                f,
    -                "Progress update error (maybe the channel has been closed)"
    -            ),
                 Self::InvalidOutpoint(outpoint) => write!(
                     f,
                     "Requested outpoint doesn't exist in the tx: {}",
                     outpoint
                 ),
                 Self::Descriptor(err) => write!(f, "Descriptor error: {}", err),
    -            Self::Encode(err) => write!(f, "Encoding error: {}", err),
                 Self::Miniscript(err) => write!(f, "Miniscript error: {}", err),
                 Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
                 Self::Bip32(err) => write!(f, "BIP32 error: {}", err),
    -            Self::Secp256k1(err) => write!(f, "Secp256k1 error: {}", err),
    -            Self::Json(err) => write!(f, "Serialize/Deserialize JSON error: {}", err),
    -            Self::Hex(err) => write!(f, "Hex decoding error: {}", err),
                 Self::Psbt(err) => write!(f, "PSBT error: {}", err),
    -            Self::PsbtParse(err) => write!(f, "Impossible to parse PSBT: {}", err),
    -            Self::MissingCachedScripts(missing_cached_scripts) => {
    -                write!(f, "Missing cached scripts: {:?}", missing_cached_scripts)
    -            }
    -            #[cfg(feature = "electrum")]
    -            Self::Electrum(err) => write!(f, "Electrum client error: {}", err),
    -            #[cfg(feature = "esplora")]
    -            Self::Esplora(err) => write!(f, "Esplora client error: {}", err),
    -            #[cfg(feature = "compact_filters")]
    -            Self::CompactFilters(err) => write!(f, "Compact filters client error: {}", err),
    -            #[cfg(feature = "key-value-db")]
    -            Self::Sled(err) => write!(f, "Sled database error: {}", err),
    -            #[cfg(feature = "rpc")]
    -            Self::Rpc(err) => write!(f, "RPC client error: {}", err),
    -            #[cfg(feature = "sqlite")]
    -            Self::Rusqlite(err) => write!(f, "SQLite error: {}", err),
             }
         }
     }
     
    -impl std::error::Error for Error {}
    +#[cfg(feature = "std")]
    +impl std::error::Error for Error {}
     
     macro_rules! impl_error {
         ( $from:ty, $to:ident ) => {
             impl_error!($from, $to, Error);
         };
         ( $from:ty, $to:ident, $impl_for:ty ) => {
    -        impl std::convert::From<$from> for $impl_for {
    +        impl core::convert::From<$from> for $impl_for {
                 fn from(err: $from) -> Self {
                     <$impl_for>::$to(err)
                 }
    @@ -650,50 +392,9 @@
         }
     }
     
    -impl_error!(bitcoin::consensus::encode::Error, Encode);
     impl_error!(miniscript::Error, Miniscript);
     impl_error!(MiniscriptPsbtError, MiniscriptPsbt);
     impl_error!(bitcoin::util::bip32::Error, Bip32);
    -impl_error!(bitcoin::secp256k1::Error, Secp256k1);
    -impl_error!(serde_json::Error, Json);
    -impl_error!(bitcoin::hashes::hex::Error, Hex);
     impl_error!(bitcoin::util::psbt::Error, Psbt);
    -impl_error!(bitcoin::util::psbt::PsbtParseError, PsbtParse);
    -
    -#[cfg(feature = "electrum")]
    -impl_error!(electrum_client::Error, Electrum);
    -#[cfg(feature = "key-value-db")]
    -impl_error!(sled::Error, Sled);
    -#[cfg(feature = "rpc")]
    -impl_error!(bitcoincore_rpc::Error, Rpc);
    -#[cfg(feature = "sqlite")]
    -impl_error!(rusqlite::Error, Rusqlite);
    -
    -#[cfg(feature = "compact_filters")]
    -impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
    -    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
    -        match other {
    -            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
    -            err => Error::CompactFilters(err),
    -        }
    -    }
    -}
    -
    -#[cfg(feature = "verify")]
    -impl From<crate::wallet::verify::VerifyError> for Error {
    -    fn from(other: crate::wallet::verify::VerifyError) -> Self {
    -        match other {
    -            crate::wallet::verify::VerifyError::Global(inner) => *inner,
    -            err => Error::Verification(err),
    -        }
    -    }
    -}
    -
    -#[cfg(feature = "esplora")]
    -impl From<crate::blockchain::esplora::EsploraError> for Error {
    -    fn from(other: crate::blockchain::esplora::EsploraError) -> Self {
    -        Error::Esplora(Box::new(other))
    -    }
    -}
     
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html deleted file mode 100644 index 85ba29060d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html +++ /dev/null @@ -1,453 +0,0 @@ -bip39.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! BIP-0039
    -
    -// TODO: maybe write our own implementation of bip39? Seems stupid to have an extra dependency for
    -// something that should be fairly simple to re-implement.
    -
    -use bitcoin::util::bip32;
    -use bitcoin::Network;
    -
    -use miniscript::ScriptContext;
    -
    -pub use bip39::{Error, Language, Mnemonic};
    -
    -type Seed = [u8; 64];
    -
    -/// Type describing entropy length (aka word count) in the mnemonic
    -pub enum WordCount {
    -    /// 12 words mnemonic (128 bits entropy)
    -    Words12 = 128,
    -    /// 15 words mnemonic (160 bits entropy)
    -    Words15 = 160,
    -    /// 18 words mnemonic (192 bits entropy)
    -    Words18 = 192,
    -    /// 21 words mnemonic (224 bits entropy)
    -    Words21 = 224,
    -    /// 24 words mnemonic (256 bits entropy)
    -    Words24 = 256,
    -}
    -
    -use super::{
    -    any_network, DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, KeyError,
    -};
    -
    -fn set_valid_on_any_network<Ctx: ScriptContext>(
    -    descriptor_key: DescriptorKey<Ctx>,
    -) -> DescriptorKey<Ctx> {
    -    // We have to pick one network to build the xprv, but since the bip39 standard doesn't
    -    // encode the network, the xprv we create is actually valid everywhere. So we override the
    -    // valid networks with `any_network()`.
    -    descriptor_key.override_valid_networks(any_network())
    -}
    -
    -/// Type for a BIP39 mnemonic with an optional passphrase
    -pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self[..])?.into())
    -    }
    -
    -    fn into_descriptor_key(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let descriptor_key = self
    -            .into_extended_key()?
    -            .into_descriptor_key(source, derivation_path)?;
    -
    -        Ok(set_valid_on_any_network(descriptor_key))
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        let (mnemonic, passphrase) = self;
    -        let seed: Seed = mnemonic.to_seed(passphrase.as_deref().unwrap_or(""));
    -
    -        seed.into_extended_key()
    -    }
    -
    -    fn into_descriptor_key(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let descriptor_key = self
    -            .into_extended_key()?
    -            .into_descriptor_key(source, derivation_path)?;
    -
    -        Ok(set_valid_on_any_network(descriptor_key))
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for (GeneratedKey<Mnemonic, Ctx>, Option<String>) {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        let (mnemonic, passphrase) = self;
    -        (mnemonic.into_key(), passphrase).into_extended_key()
    -    }
    -
    -    fn into_descriptor_key(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let (mnemonic, passphrase) = self;
    -        (mnemonic.into_key(), passphrase).into_descriptor_key(source, derivation_path)
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        (self, None).into_extended_key()
    -    }
    -
    -    fn into_descriptor_key(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let descriptor_key = self
    -            .into_extended_key()?
    -            .into_descriptor_key(source, derivation_path)?;
    -
    -        Ok(set_valid_on_any_network(descriptor_key))
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
    -    type Entropy = [u8; 32];
    -
    -    type Options = (WordCount, Language);
    -    type Error = Option<bip39::Error>;
    -
    -    fn generate_with_entropy(
    -        (word_count, language): Self::Options,
    -        entropy: Self::Entropy,
    -    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
    -        let entropy = &entropy.as_ref()[..(word_count as usize / 8)];
    -        let mnemonic = Mnemonic::from_entropy_in(language, entropy)?;
    -
    -        Ok(GeneratedKey::new(mnemonic, any_network()))
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::util::bip32;
    -
    -    use bip39::{Language, Mnemonic};
    -
    -    use crate::keys::{any_network, GeneratableKey, GeneratedKey};
    -
    -    use super::WordCount;
    -
    -    #[test]
    -    fn test_keys_bip39_mnemonic() {
    -        let mnemonic =
    -            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
    -        let mnemonic = Mnemonic::parse_in(Language::English, mnemonic).unwrap();
    -        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
    -
    -        let key = (mnemonic, path);
    -        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
    -        assert_eq!(desc.to_string(), "wpkh([be83839f/44'/0'/0']xpub6DCQ1YcqvZtSwGWMrwHELPehjWV3f2MGZ69yBADTxFEUAoLwb5Mp5GniQK6tTp3AgbngVz9zEFbBJUPVnkG7LFYt8QMTfbrNqs6FNEwAPKA/0/*)#0r8v4nkv");
    -        assert_eq!(keys.len(), 1);
    -        assert_eq!(networks.len(), 4);
    -    }
    -
    -    #[test]
    -    fn test_keys_bip39_mnemonic_passphrase() {
    -        let mnemonic =
    -            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
    -        let mnemonic = Mnemonic::parse_in(Language::English, mnemonic).unwrap();
    -        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
    -
    -        let key = ((mnemonic, Some("passphrase".into())), path);
    -        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
    -        assert_eq!(desc.to_string(), "wpkh([8f6cb80c/44'/0'/0']xpub6DWYS8bbihFevy29M4cbw4ZR3P5E12jB8R88gBDWCTCNpYiDHhYWNywrCF9VZQYagzPmsZpxXpytzSoxynyeFr4ZyzheVjnpLKuse4fiwZw/0/*)#h0j0tg5m");
    -        assert_eq!(keys.len(), 1);
    -        assert_eq!(networks.len(), 4);
    -    }
    -
    -    #[test]
    -    fn test_keys_generate_bip39() {
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate_with_entropy(
    -                (WordCount::Words12, Language::English),
    -                crate::keys::test::TEST_ENTROPY,
    -            )
    -            .unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -        assert_eq!(
    -            generated_mnemonic.to_string(),
    -            "primary fetch primary fetch primary fetch primary fetch primary fetch primary fever"
    -        );
    -
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate_with_entropy(
    -                (WordCount::Words24, Language::English),
    -                crate::keys::test::TEST_ENTROPY,
    -            )
    -            .unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -        assert_eq!(generated_mnemonic.to_string(), "primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary foster");
    -    }
    -
    -    #[test]
    -    fn test_keys_generate_bip39_random() {
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate((WordCount::Words12, Language::English)).unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate((WordCount::Words24, Language::English)).unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html index f4df7c0b68..62616882c8 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html @@ -1,5 +1,4 @@ -mod.rs - source
    1
    +mod.rs - source
    1
     2
     3
     4
    @@ -993,6 +992,8 @@
     992
     993
     994
    +995
    +996
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -1006,11 +1007,13 @@
     
     //! Key formats
     
    -use std::any::TypeId;
    -use std::collections::HashSet;
    -use std::marker::PhantomData;
    -use std::ops::Deref;
    -use std::str::FromStr;
    +use crate::collections::HashSet;
    +use alloc::string::{String, ToString};
    +use alloc::vec::Vec;
    +use core::any::TypeId;
    +use core::marker::PhantomData;
    +use core::ops::Deref;
    +use core::str::FromStr;
     
     use bitcoin::secp256k1::{self, Secp256k1, Signing};
     
    @@ -1272,7 +1275,7 @@
     ///
     /// ```compile_fail
     /// use bdk::bitcoin::PublicKey;
    -/// use std::str::FromStr;
    +/// use core::str::FromStr;
     ///
     /// use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError};
     ///
    @@ -1455,12 +1458,11 @@
     /// [`ExtendedPubKey`]: (bip32::ExtendedPubKey)
     pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized {
         /// Consume `self` and turn it into an [`ExtendedKey`]
    -    ///
    -    /// This can be used to get direct access to `xprv`s and `xpub`s for types that implement this trait,
    -    /// like [`Mnemonic`](bip39::Mnemonic) when the `keys-bip39` feature is enabled.
         #[cfg_attr(
             feature = "keys-bip39",
             doc = r##"
    +This can be used to get direct access to `xprv`s and `xpub`s for types that implement this trait,
    +like [`Mnemonic`](bip39::Mnemonic) when the `keys-bip39` feature is enabled.
     ```rust
     use bdk::bitcoin::Network;
     use bdk::keys::{DerivableKey, ExtendedKey};
    @@ -1614,7 +1616,7 @@ let xprv = xkey.into_xprv(Network::Bitcoin).unwrap();
         /// Extra options required by the `generate_with_entropy`
         type Options;
         /// Returned error in case of failure
    -    type Error: std::fmt::Debug;
    +    type Error: core::fmt::Debug;
     
         /// Generate a key given the extra options and the entropy
         fn generate_with_entropy(
    @@ -1941,7 +1943,8 @@ let xprv = xkey.into_xprv(Network::Bitcoin).unwrap();
         }
     }
     
    -impl std::error::Error for KeyError {}
    +#[cfg(feature = "std")]
    +impl std::error::Error for KeyError {}
     
     #[cfg(test)]
     pub mod test {
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html
    index 88e6b53030..21e2f1645d 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html
    @@ -1,5 +1,4 @@
    -lib.rs - source
    1
    +lib.rs - source
    1
     2
     3
     4
    @@ -45,517 +44,31 @@
     44
     45
     46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -// rustdoc will warn if there are missing docs
    -#![warn(missing_docs)]
    -// only enables the `doc_cfg` feature when
    -// the `docsrs` configuration attribute is defined
    -#![cfg_attr(docsrs, feature(doc_cfg))]
    -#![cfg_attr(
    -    docsrs,
    -    doc(html_logo_url = "https://github.com/bitcoindevkit/bdk/raw/master/static/bdk.png")
    -)]
    -
    -//! A modern, lightweight, descriptor-based wallet library written in Rust.
    -//!
    -//! # About
    -//!
    -//! The BDK library aims to be the core building block for Bitcoin wallets of any kind.
    -//!
    -//! * It uses [Miniscript](https://github.com/rust-bitcoin/rust-miniscript) to support descriptors with generalized conditions. This exact same library can be used to build
    -//!   single-sig wallets, multisigs, timelocked contracts and more.
    -//! * It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
    -//! * It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
    -//! * It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
    -//!
    -//! # A Tour of BDK
    -//!
    -//! BDK consists of a number of modules that provide a range of functionality
    -//! essential for implementing descriptor based Bitcoin wallet applications in Rust. In this
    -//! section, we will take a brief tour of BDK, summarizing the major APIs and
    -//! their uses.
    -//!
    -//! The easiest way to get started is to add bdk to your dependencies with the default features.
    -//! The default features include a simple key-value database ([`sled`](sled)) to cache
    -//! blockchain data and an [electrum](https://docs.rs/electrum-client/) blockchain client to
    -//! interact with the bitcoin P2P network.
    -//!
    -//! # Examples
    -#![cfg_attr(
    -    feature = "electrum",
    -    doc = r##"
    -## Sync the balance of a descriptor
    -
    -```no_run
    -use bdk::{Wallet, SyncOptions};
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::ElectrumBlockchain;
    -use bdk::electrum_client::Client;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -    let blockchain = ElectrumBlockchain::from(client);
    -    let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -    )?;
    -
    -    wallet.sync(&blockchain, SyncOptions::default())?;
    -
    -    println!("Descriptor balance: {} SAT", wallet.get_balance()?);
    -
    -    Ok(())
    -}
    -```
    -"##
    -)]
    -//!
    -//! ## Generate a few addresses
    -//!
    -//! ### Example
    -//! ```
    -//! use bdk::{Wallet};
    -//! use bdk::database::MemoryDatabase;
    -//! use bdk::wallet::AddressIndex::New;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//! let wallet = Wallet::new(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!     )?;
    -//!
    -//!     println!("Address #0: {}", wallet.get_address(New)?);
    -//!     println!("Address #1: {}", wallet.get_address(New)?);
    -//!     println!("Address #2: {}", wallet.get_address(New)?);
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -#![cfg_attr(
    -    feature = "electrum",
    -    doc = r##"
    -## Create a transaction
    -
    -```no_run
    -use bdk::{FeeRate, Wallet, SyncOptions};
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::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(),
    -    )?;
    -    let blockchain = ElectrumBlockchain::from(client);
    -
    -    wallet.sync(&blockchain, SyncOptions::default())?;
    -
    -    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: {}", &psbt);
    -
    -    Ok(())
    -}
    -```
    -"##
    -)]
    -//!
    -//! ## Sign a transaction
    -//!
    -//! ```no_run
    -//! use std::str::FromStr;
    -//!
    -//! use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
    -//!
    -//! use bdk::{Wallet, SignOptions};
    -//! use bdk::database::MemoryDatabase;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//!     let wallet = Wallet::new(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!     )?;
    -//!
    -//!     let psbt = "...";
    -//!     let mut psbt = Psbt::from_str(psbt)?;
    -//!
    -//!     let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -//!
    -//! # Feature flags
    -//!
    -//! BDK uses a set of [feature flags](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section)
    -//! to reduce the amount of compiled code by allowing projects to only enable the features they need.
    -//! By default, BDK enables two internal features, `key-value-db` and `electrum`.
    -//!
    -//! If you are new to BDK we recommended that you use the default features which will enable
    -//! basic descriptor wallet functionality. More advanced users can disable the `default` features
    -//! (`--no-default-features`) and build the BDK library with only the features you need.
    +
    #![doc = include_str!("../README.md")]
    +#![no_std]
    +#[cfg(feature = "std")]
    +#[macro_use]
    +extern crate std;
     
    -//! Below is a list of the available feature flags and the additional functionality they provide.
    -//!
    -//! * `all-keys`: all features for working with bitcoin keys
    -//! * `async-interface`: async functions in bdk traits
    -//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
    -//!
    -//! # Internal features
    -//!
    -//! These features do not expose any new API, but influence internal implementation aspects of
    -//! BDK.
    -//!
    -//! * `compact_filters`: [`compact_filters`](crate::blockchain::compact_filters) client protocol for interacting with the bitcoin P2P network
    -//! * `electrum`: [`electrum`](crate::blockchain::electrum) client protocol for interacting with electrum servers
    -//! * `esplora`: [`esplora`](crate::blockchain::esplora) client protocol for interacting with blockstream [electrs](https://github.com/Blockstream/electrs) servers
    -//! * `key-value-db`: key value [`database`](crate::database) based on [`sled`](crate::sled) for caching blockchain data
    +#[doc(hidden)]
    +#[macro_use]
    +pub extern crate alloc;
     
    -pub extern crate bitcoin;
    +pub extern crate bitcoin;
    +#[cfg(feature = "hardware-signer")]
    +pub extern crate hwi;
     extern crate log;
     pub extern crate miniscript;
     extern crate serde;
    -#[macro_use]
    -extern crate serde_json;
    -#[cfg(feature = "hardware-signer")]
    -pub extern crate hwi;
    -
    -#[cfg(all(feature = "reqwest", feature = "ureq"))]
    -compile_error!("Features reqwest and ureq are mutually exclusive and cannot be enabled together");
    -
    -#[cfg(all(feature = "async-interface", feature = "electrum"))]
    -compile_error!(
    -    "Features async-interface and electrum are mutually exclusive and cannot be enabled together"
    -);
    -
    -#[cfg(all(feature = "async-interface", feature = "ureq"))]
    -compile_error!(
    -    "Features async-interface and ureq are mutually exclusive and cannot be enabled together"
    -);
    -
    -#[cfg(all(feature = "async-interface", feature = "compact_filters"))]
    -compile_error!(
    -    "Features async-interface and compact_filters are mutually exclusive and cannot be enabled together"
    -);
    +extern crate serde_json;
     
     #[cfg(feature = "keys-bip39")]
     extern crate bip39;
     
    -#[cfg(feature = "async-interface")]
    -#[macro_use]
    -extern crate async_trait;
    -#[macro_use]
    -extern crate bdk_macros;
    -
    -#[cfg(feature = "rpc")]
    -pub extern crate bitcoincore_rpc;
    -
    -#[cfg(feature = "electrum")]
    -pub extern crate electrum_client;
    -
    -#[cfg(feature = "esplora")]
    -pub extern crate esplora_client;
    -
    -#[cfg(feature = "key-value-db")]
    -pub extern crate sled;
    -
    -#[cfg(feature = "sqlite")]
    -pub extern crate rusqlite;
    -
    -// We should consider putting this under a feature flag but we need the macro in doctests so we need
    -// to wait until https://github.com/rust-lang/rust/issues/67295 is fixed.
    -//
    -// Stuff in here is too rough to document atm
    -#[doc(hidden)]
    -#[macro_use]
    -pub mod testutils;
    -
    -#[cfg(test)]
    -extern crate assert_matches;
    -
     #[allow(unused_imports)]
     #[macro_use]
     pub(crate) mod error;
    -pub mod blockchain;
    -pub mod database;
     pub mod descriptor;
    -#[cfg(feature = "test-md-docs")]
    -mod doctest;
     pub mod keys;
     pub mod psbt;
     pub(crate) mod types;
    @@ -568,12 +81,14 @@ fn main() -> Result<(), bdk::Error> {
     pub use wallet::signer;
     pub use wallet::signer::SignOptions;
     pub use wallet::tx_builder::TxBuilder;
    -pub use wallet::SyncOptions;
     pub use wallet::Wallet;
     
     /// Get the version of BDK at runtime
     pub fn version() -> &'static str {
         env!("CARGO_PKG_VERSION", "unknown")
     }
    +
    +pub use bdk_chain as chain;
    +pub(crate) use bdk_chain::collections;
     
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html index 44008010b8..97d8f21d7b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html @@ -1,5 +1,4 @@ -mod.rs - source
    1
    +mod.rs - source
    1
     2
     3
     4
    @@ -78,166 +77,6 @@
     77
     78
     79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -252,6 +91,7 @@
     //! Additional functions on the `rust-bitcoin` `PartiallySignedTransaction` structure.
     
     use crate::FeeRate;
    +use alloc::vec::Vec;
     use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
     use bitcoin::TxOut;
     
    @@ -316,166 +156,5 @@
             })
         }
     }
    -
    -#[cfg(test)]
    -mod test {
    -    use crate::bitcoin::TxIn;
    -    use crate::psbt::Psbt;
    -    use crate::wallet::AddressIndex;
    -    use crate::wallet::AddressIndex::New;
    -    use crate::wallet::{get_funded_wallet, test::get_test_wpkh};
    -    use crate::{psbt, FeeRate, SignOptions};
    -    use std::str::FromStr;
    -
    -    // from bip 174
    -    const PSBT_STR: &str = "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA";
    -
    -    #[test]
    -    #[should_panic(expected = "InputIndexOutOfRange")]
    -    fn test_psbt_malformed_psbt_input_legacy() {
    -        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        psbt.inputs.push(psbt_bip.inputs[0].clone());
    -        let options = SignOptions {
    -            trust_witness_utxo: true,
    -            ..Default::default()
    -        };
    -        let _ = wallet.sign(&mut psbt, options).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InputIndexOutOfRange")]
    -    fn test_psbt_malformed_psbt_input_segwit() {
    -        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        psbt.inputs.push(psbt_bip.inputs[1].clone());
    -        let options = SignOptions {
    -            trust_witness_utxo: true,
    -            ..Default::default()
    -        };
    -        let _ = wallet.sign(&mut psbt, options).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InputIndexOutOfRange")]
    -    fn test_psbt_malformed_tx_input() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        psbt.unsigned_tx.input.push(TxIn::default());
    -        let options = SignOptions {
    -            trust_witness_utxo: true,
    -            ..Default::default()
    -        };
    -        let _ = wallet.sign(&mut psbt, options).unwrap();
    -    }
    -
    -    #[test]
    -    fn test_psbt_sign_with_finalized() {
    -        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        // add a finalized input
    -        psbt.inputs.push(psbt_bip.inputs[0].clone());
    -        psbt.unsigned_tx
    -            .input
    -            .push(psbt_bip.unsigned_tx.input[0].clone());
    -
    -        let _ = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
    -    }
    -
    -    #[test]
    -    fn test_psbt_fee_rate_with_witness_utxo() {
    -        use psbt::PsbtUtils;
    -
    -        let expected_fee_rate = 1.2345;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        let fee_amount = psbt.fee_amount();
    -        assert!(fee_amount.is_some());
    -
    -        let unfinalized_fee_rate = psbt.fee_rate().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let finalized_fee_rate = psbt.fee_rate().unwrap();
    -        assert!(finalized_fee_rate.as_sat_per_vb() >= expected_fee_rate);
    -        assert!(finalized_fee_rate.as_sat_per_vb() < unfinalized_fee_rate.as_sat_per_vb());
    -    }
    -
    -    #[test]
    -    fn test_psbt_fee_rate_with_nonwitness_utxo() {
    -        use psbt::PsbtUtils;
    -
    -        let expected_fee_rate = 1.2345;
    -
    -        let (wallet, _, _) = get_funded_wallet("pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        let fee_amount = psbt.fee_amount();
    -        assert!(fee_amount.is_some());
    -        let unfinalized_fee_rate = psbt.fee_rate().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let finalized_fee_rate = psbt.fee_rate().unwrap();
    -        assert!(finalized_fee_rate.as_sat_per_vb() >= expected_fee_rate);
    -        assert!(finalized_fee_rate.as_sat_per_vb() < unfinalized_fee_rate.as_sat_per_vb());
    -    }
    -
    -    #[test]
    -    fn test_psbt_fee_rate_with_missing_txout() {
    -        use psbt::PsbtUtils;
    -
    -        let expected_fee_rate = 1.2345;
    -
    -        let (wpkh_wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wpkh_wallet.get_address(New).unwrap();
    -        let mut builder = wpkh_wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
    -        let (mut wpkh_psbt, _) = builder.finish().unwrap();
    -
    -        wpkh_psbt.inputs[0].witness_utxo = None;
    -        wpkh_psbt.inputs[0].non_witness_utxo = None;
    -        assert!(wpkh_psbt.fee_amount().is_none());
    -        assert!(wpkh_psbt.fee_rate().is_none());
    -
    -        let (pkh_wallet, _, _) = get_funded_wallet("pkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = pkh_wallet.get_address(New).unwrap();
    -        let mut builder = pkh_wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(expected_fee_rate));
    -        let (mut pkh_psbt, _) = builder.finish().unwrap();
    -
    -        pkh_psbt.inputs[0].non_witness_utxo = None;
    -        assert!(pkh_psbt.fee_amount().is_none());
    -        assert!(pkh_psbt.fee_rate().is_none());
    -    }
    -}
     
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html deleted file mode 100644 index 34d9b190c8..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html +++ /dev/null @@ -1,469 +0,0 @@ -mod.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -#![allow(missing_docs)]
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-blockchains")]
    -pub mod blockchain_tests;
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-blockchains")]
    -pub mod configurable_blockchain_tests;
    -
    -use bitcoin::{Address, Txid};
    -
    -#[derive(Clone, Debug)]
    -pub struct TestIncomingInput {
    -    pub txid: Txid,
    -    pub vout: u32,
    -    pub sequence: Option<u32>,
    -}
    -
    -impl TestIncomingInput {
    -    pub fn new(txid: Txid, vout: u32, sequence: Option<u32>) -> Self {
    -        Self {
    -            txid,
    -            vout,
    -            sequence,
    -        }
    -    }
    -
    -    #[cfg(feature = "test-blockchains")]
    -    pub fn into_raw_tx_input(self) -> bitcoincore_rpc::json::CreateRawTransactionInput {
    -        bitcoincore_rpc::json::CreateRawTransactionInput {
    -            txid: self.txid,
    -            vout: self.vout,
    -            sequence: self.sequence,
    -        }
    -    }
    -}
    -
    -#[derive(Clone, Debug)]
    -pub struct TestIncomingOutput {
    -    pub value: u64,
    -    pub to_address: String,
    -}
    -
    -impl TestIncomingOutput {
    -    pub fn new(value: u64, to_address: Address) -> Self {
    -        Self {
    -            value,
    -            to_address: to_address.to_string(),
    -        }
    -    }
    -}
    -
    -#[derive(Clone, Debug)]
    -pub struct TestIncomingTx {
    -    pub input: Vec<TestIncomingInput>,
    -    pub output: Vec<TestIncomingOutput>,
    -    pub min_confirmations: Option<u64>,
    -    pub locktime: Option<i64>,
    -    pub replaceable: Option<bool>,
    -}
    -
    -impl TestIncomingTx {
    -    pub fn new(
    -        input: Vec<TestIncomingInput>,
    -        output: Vec<TestIncomingOutput>,
    -        min_confirmations: Option<u64>,
    -        locktime: Option<i64>,
    -        replaceable: Option<bool>,
    -    ) -> Self {
    -        Self {
    -            input,
    -            output,
    -            min_confirmations,
    -            locktime,
    -            replaceable,
    -        }
    -    }
    -
    -    pub fn add_input(&mut self, input: TestIncomingInput) {
    -        self.input.push(input);
    -    }
    -
    -    pub fn add_output(&mut self, output: TestIncomingOutput) {
    -        self.output.push(output);
    -    }
    -}
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! testutils {
    -    ( @external $descriptors:expr, $child:expr ) => ({
    -        use $crate::bitcoin::secp256k1::Secp256k1;
    -        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
    -
    -        let secp = Secp256k1::new();
    -
    -        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.0).expect("Failed to parse descriptor in `testutils!(@external)`").0;
    -        parsed.at_derivation_index($child).address(bitcoin::Network::Regtest).expect("No address form")
    -    });
    -    ( @internal $descriptors:expr, $child:expr ) => ({
    -        use $crate::bitcoin::secp256k1::Secp256k1;
    -        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
    -
    -        let secp = Secp256k1::new();
    -
    -        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.1.expect("Missing internal descriptor")).expect("Failed to parse descriptor in `testutils!(@internal)`").0;
    -        parsed.at_derivation_index($child).address($crate::bitcoin::Network::Regtest).expect("No address form")
    -    });
    -    ( @e $descriptors:expr, $child:expr ) => ({ testutils!(@external $descriptors, $child) });
    -    ( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) });
    -    ( @addr $addr:expr ) => ({ $addr });
    -
    -    ( @tx ( $( ( $( $addr:tt )* ) => $amount:expr ),+ ) $( ( @inputs $( ($txid:expr, $vout:expr) ),+ ) )? $( ( @locktime $locktime:expr ) )? $( ( @confirmations $confirmations:expr ) )? $( ( @replaceable $replaceable:expr ) )? ) => ({
    -        let outs = vec![$( $crate::testutils::TestIncomingOutput::new($amount, testutils!( $($addr)* ))),+];
    -        let _ins: Vec<$crate::testutils::TestIncomingInput> = vec![];
    -        $(
    -            let _ins = vec![$( $crate::testutils::TestIncomingInput { txid: $txid, vout: $vout, sequence: None }),+];
    -        )?
    -
    -        let locktime = None::<i64>$(.or(Some($locktime)))?;
    -
    -        let min_confirmations = None::<u64>$(.or(Some($confirmations)))?;
    -        let replaceable = None::<bool>$(.or(Some($replaceable)))?;
    -
    -        $crate::testutils::TestIncomingTx::new(_ins, outs, min_confirmations, locktime, replaceable)
    -    });
    -
    -    ( @literal $key:expr ) => ({
    -        let key = $key.to_string();
    -        (key, None::<String>, None::<String>)
    -    });
    -    ( @generate_xprv $( $external_path:expr )? $( ,$internal_path:expr )? ) => ({
    -        use rand::Rng;
    -
    -        let mut seed = [0u8; 32];
    -        rand::thread_rng().fill(&mut seed[..]);
    -
    -        let key = $crate::bitcoin::util::bip32::ExtendedPrivKey::new_master(
    -            $crate::bitcoin::Network::Testnet,
    -            &seed,
    -        );
    -
    -        let external_path = None::<String>$(.or(Some($external_path.to_string())))?;
    -        let internal_path = None::<String>$(.or(Some($internal_path.to_string())))?;
    -
    -        (key.unwrap().to_string(), external_path, internal_path)
    -    });
    -    ( @generate_wif ) => ({
    -        use rand::Rng;
    -
    -        let mut key = [0u8; $crate::bitcoin::secp256k1::constants::SECRET_KEY_SIZE];
    -        rand::thread_rng().fill(&mut key[..]);
    -
    -        ($crate::bitcoin::PrivateKey {
    -            compressed: true,
    -            network: $crate::bitcoin::Network::Testnet,
    -            key: $crate::bitcoin::secp256k1::SecretKey::from_slice(&key).unwrap(),
    -        }.to_string(), None::<String>, None::<String>)
    -    });
    -
    -    ( @keys ( $( $alias:expr => ( $( $key_type:tt )* ) ),+ ) ) => ({
    -        let mut map = std::collections::HashMap::new();
    -        $(
    -            let alias: &str = $alias;
    -            map.insert(alias, testutils!( $($key_type)* ));
    -        )+
    -
    -        map
    -    });
    -
    -    ( @descriptors ( $external_descriptor:expr ) $( ( $internal_descriptor:expr ) )? $( ( @keys $( $keys:tt )* ) )* ) => ({
    -        use std::str::FromStr;
    -        use std::collections::HashMap;
    -        use std::convert::Infallible;
    -
    -        use $crate::miniscript::descriptor::Descriptor;
    -        use $crate::miniscript::TranslatePk;
    -
    -        struct Translator {
    -            keys: HashMap<&'static str, (String, Option<String>, Option<String>)>,
    -            is_internal: bool,
    -        }
    -
    -        impl $crate::miniscript::Translator<String, String, Infallible> for Translator {
    -            fn pk(&mut self, pk: &String) -> Result<String, Infallible> {
    -                match self.keys.get(pk.as_str()) {
    -                    Some((key, ext_path, int_path)) => {
    -                        let path = if self.is_internal { int_path } else { ext_path };
    -                        Ok(format!("{}{}", key, path.clone().unwrap_or_default()))
    -                    }
    -                    None => Ok(pk.clone()),
    -                }
    -            }
    -            fn sha256(&mut self, sha256: &String) -> Result<String, Infallible> { Ok(sha256.clone()) }
    -            fn hash256(&mut self, hash256: &String) -> Result<String, Infallible> { Ok(hash256.clone()) }
    -            fn ripemd160(&mut self, ripemd160: &String) -> Result<String, Infallible> { Ok(ripemd160.clone()) }
    -            fn hash160(&mut self, hash160: &String) -> Result<String, Infallible> { Ok(hash160.clone()) }
    -        }
    -
    -        #[allow(unused_assignments, unused_mut)]
    -        let mut keys = HashMap::new();
    -        $(
    -            keys = testutils!{ @keys $( $keys )* };
    -        )*
    -
    -        let mut translator = Translator { keys, is_internal: false };
    -
    -        let external: Descriptor<String> = FromStr::from_str($external_descriptor).unwrap();
    -        let external = external.translate_pk(&mut translator).expect("Infallible conversion");
    -        let external = external.to_string();
    -
    -        translator.is_internal = true;
    -
    -        let internal = None::<String>$(.or({
    -            let internal: Descriptor<String> = FromStr::from_str($internal_descriptor).unwrap();
    -            let internal = internal.translate_pk(&mut translator).expect("Infallible conversion");
    -            Some(internal.to_string())
    -        }))?;
    -
    -        (external, internal)
    -    })
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html index efb1e41621..7167ef338c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html @@ -1,5 +1,4 @@ -types.rs - source
    1
    +types.rs - source
    1
     2
     3
     4
    @@ -332,190 +331,6 @@
     331
     332
     333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -527,16 +342,18 @@
     // You may not use this file except in accordance with one or both of these
     // licenses.
     
    -use std::convert::AsRef;
    -use std::ops::Sub;
    +use alloc::boxed::Box;
    +use core::convert::AsRef;
    +use core::ops::Sub;
     
    +use bdk_chain::ConfirmationTime;
     use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
     use bitcoin::{hash_types::Txid, util::psbt};
     
     use serde::{Deserialize, Serialize};
     
     /// Types of keychains
    -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
    +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
     pub enum KeychainKind {
         /// External
         External = 0,
    @@ -641,7 +458,7 @@
         }
     }
     
    -impl std::default::Default for FeeRate {
    +impl Default for FeeRate {
         fn default() -> Self {
             FeeRate::default_min_relay_fee()
         }
    @@ -681,6 +498,10 @@
         pub keychain: KeychainKind,
         /// Whether this UTXO is spent or not
         pub is_spent: bool,
    +    /// The derivation index for the script pubkey in the wallet
    +    pub derivation_index: u32,
    +    /// The confirmation time for transaction containing this utxo
    +    pub confirmation_time: ConfirmationTime,
     }
     
     /// A [`Utxo`] with its `satisfaction_weight`.
    @@ -754,220 +575,30 @@
         /// Sent value (sats)
         /// Sum of owned inputs of this transaction.
         pub sent: u64,
    -    /// Fee value (sats) if confirmed.
    -    /// The availability of the fee depends on the backend. It's never `None` with an Electrum
    -    /// Server backend, but it could be `None` with a Bitcoin RPC node without txindex that receive
    -    /// funds while offline.
    +    /// Fee value in sats if it was available.
         pub fee: Option<u64>,
         /// If the transaction is confirmed, contains height and Unix timestamp of the block containing the
         /// transaction, unconfirmed transaction contains `None`.
    -    pub confirmation_time: Option<BlockTime>,
    +    pub confirmation_time: ConfirmationTime,
     }
     
     impl PartialOrd for TransactionDetails {
    -    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
    +    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
             Some(self.cmp(other))
         }
     }
     
     impl Ord for TransactionDetails {
    -    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
    +    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
             self.confirmation_time
                 .cmp(&other.confirmation_time)
                 .then_with(|| self.txid.cmp(&other.txid))
         }
     }
     
    -/// Block height and timestamp of a block
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
    -pub struct BlockTime {
    -    /// confirmation block height
    -    pub height: u32,
    -    /// confirmation block timestamp
    -    pub timestamp: u64,
    -}
    -
    -impl PartialOrd for BlockTime {
    -    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
    -        Some(self.cmp(other))
    -    }
    -}
    -
    -impl Ord for BlockTime {
    -    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
    -        self.height
    -            .cmp(&other.height)
    -            .then_with(|| self.timestamp.cmp(&other.timestamp))
    -    }
    -}
    -
    -/// **DEPRECATED**: Confirmation time of a transaction
    -///
    -/// The structure has been renamed to `BlockTime`
    -#[deprecated(note = "This structure has been renamed to `BlockTime`")]
    -pub type ConfirmationTime = BlockTime;
    -
    -impl BlockTime {
    -    /// Returns `Some` `BlockTime` if both `height` and `timestamp` are `Some`
    -    pub fn new(height: Option<u32>, timestamp: Option<u64>) -> Option<Self> {
    -        match (height, timestamp) {
    -            (Some(height), Some(timestamp)) => Some(BlockTime { height, timestamp }),
    -            _ => None,
    -        }
    -    }
    -}
    -
    -/// Balance differentiated in various categories
    -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
    -pub struct Balance {
    -    /// All coinbase outputs not yet matured
    -    pub immature: u64,
    -    /// Unconfirmed UTXOs generated by a wallet tx
    -    pub trusted_pending: u64,
    -    /// Unconfirmed UTXOs received from an external wallet
    -    pub untrusted_pending: u64,
    -    /// Confirmed and immediately spendable balance
    -    pub confirmed: u64,
    -}
    -
    -impl Balance {
    -    /// Get sum of trusted_pending and confirmed coins
    -    pub fn get_spendable(&self) -> u64 {
    -        self.confirmed + self.trusted_pending
    -    }
    -
    -    /// Get the whole balance visible to the wallet
    -    pub fn get_total(&self) -> u64 {
    -        self.confirmed + self.trusted_pending + self.untrusted_pending + self.immature
    -    }
    -}
    -
    -impl std::fmt::Display for Balance {
    -    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    -        write!(
    -            f,
    -            "{{ immature: {}, trusted_pending: {}, untrusted_pending: {}, confirmed: {} }}",
    -            self.immature, self.trusted_pending, self.untrusted_pending, self.confirmed
    -        )
    -    }
    -}
    -
    -impl std::ops::Add for Balance {
    -    type Output = Self;
    -
    -    fn add(self, other: Self) -> Self {
    -        Self {
    -            immature: self.immature + other.immature,
    -            trusted_pending: self.trusted_pending + other.trusted_pending,
    -            untrusted_pending: self.untrusted_pending + other.untrusted_pending,
    -            confirmed: self.confirmed + other.confirmed,
    -        }
    -    }
    -}
    -
    -impl std::iter::Sum for Balance {
    -    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
    -        iter.fold(
    -            Balance {
    -                ..Default::default()
    -            },
    -            |a, b| a + b,
    -        )
    -    }
    -}
    -
     #[cfg(test)]
     mod tests {
         use super::*;
    -    use bitcoin::hashes::Hash;
    -
    -    #[test]
    -    fn sort_block_time() {
    -        let block_time_a = BlockTime {
    -            height: 100,
    -            timestamp: 100,
    -        };
    -
    -        let block_time_b = BlockTime {
    -            height: 100,
    -            timestamp: 110,
    -        };
    -
    -        let block_time_c = BlockTime {
    -            height: 0,
    -            timestamp: 0,
    -        };
    -
    -        let mut vec = vec![
    -            block_time_a.clone(),
    -            block_time_b.clone(),
    -            block_time_c.clone(),
    -        ];
    -        vec.sort();
    -        let expected = vec![block_time_c, block_time_a, block_time_b];
    -
    -        assert_eq!(vec, expected)
    -    }
    -
    -    #[test]
    -    fn sort_tx_details() {
    -        let block_time_a = BlockTime {
    -            height: 100,
    -            timestamp: 100,
    -        };
    -
    -        let block_time_b = BlockTime {
    -            height: 0,
    -            timestamp: 0,
    -        };
    -
    -        let tx_details_a = TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_inner([0; 32]),
    -            received: 0,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: None,
    -        };
    -
    -        let tx_details_b = TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_inner([0; 32]),
    -            received: 0,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(block_time_a),
    -        };
    -
    -        let tx_details_c = TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_inner([0; 32]),
    -            received: 0,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(block_time_b.clone()),
    -        };
    -
    -        let tx_details_d = TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_inner([1; 32]),
    -            received: 0,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(block_time_b),
    -        };
    -
    -        let mut vec = vec![
    -            tx_details_a.clone(),
    -            tx_details_b.clone(),
    -            tx_details_c.clone(),
    -            tx_details_d.clone(),
    -        ];
    -        vec.sort();
    -        let expected = vec![tx_details_a, tx_details_c, tx_details_d, tx_details_b];
    -
    -        assert_eq!(vec, expected)
    -    }
     
         #[test]
         fn can_store_feerate_in_const() {
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html
    index 56d5d96901..e42b2e2647 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html
    @@ -1,5 +1,4 @@
    -coin_selection.rs - source
    1
    +coin_selection.rs - source
    1
     2
     3
     4
    @@ -1436,164 +1435,6 @@
     1435
     1436
     1437
    -1438
    -1439
    -1440
    -1441
    -1442
    -1443
    -1444
    -1445
    -1446
    -1447
    -1448
    -1449
    -1450
    -1451
    -1452
    -1453
    -1454
    -1455
    -1456
    -1457
    -1458
    -1459
    -1460
    -1461
    -1462
    -1463
    -1464
    -1465
    -1466
    -1467
    -1468
    -1469
    -1470
    -1471
    -1472
    -1473
    -1474
    -1475
    -1476
    -1477
    -1478
    -1479
    -1480
    -1481
    -1482
    -1483
    -1484
    -1485
    -1486
    -1487
    -1488
    -1489
    -1490
    -1491
    -1492
    -1493
    -1494
    -1495
    -1496
    -1497
    -1498
    -1499
    -1500
    -1501
    -1502
    -1503
    -1504
    -1505
    -1506
    -1507
    -1508
    -1509
    -1510
    -1511
    -1512
    -1513
    -1514
    -1515
    -1516
    -1517
    -1518
    -1519
    -1520
    -1521
    -1522
    -1523
    -1524
    -1525
    -1526
    -1527
    -1528
    -1529
    -1530
    -1531
    -1532
    -1533
    -1534
    -1535
    -1536
    -1537
    -1538
    -1539
    -1540
    -1541
    -1542
    -1543
    -1544
    -1545
    -1546
    -1547
    -1548
    -1549
    -1550
    -1551
    -1552
    -1553
    -1554
    -1555
    -1556
    -1557
    -1558
    -1559
    -1560
    -1561
    -1562
    -1563
    -1564
    -1565
    -1566
    -1567
    -1568
    -1569
    -1570
    -1571
    -1572
    -1573
    -1574
    -1575
    -1576
    -1577
    -1578
    -1579
    -1580
    -1581
    -1582
    -1583
    -1584
    -1585
    -1586
    -1587
    -1588
    -1589
    -1590
    -1591
    -1592
    -1593
    -1594
    -1595
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -1623,17 +1464,15 @@
     //! # use std::str::FromStr;
     //! # use bitcoin::*;
     //! # use bdk::wallet::{self, coin_selection::*};
    -//! # use bdk::database::Database;
     //! # use bdk::*;
     //! # use bdk::wallet::coin_selection::decide_change;
     //! # const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4) * 4;
     //! #[derive(Debug)]
     //! struct AlwaysSpendEverything;
     //!
    -//! impl<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
    +//! impl CoinSelectionAlgorithm for AlwaysSpendEverything {
     //!     fn coin_select(
     //!         &self,
    -//!         database: &D,
     //!         required_utxos: Vec<WeightedUtxo>,
     //!         optional_utxos: Vec<WeightedUtxo>,
     //!         fee_rate: FeeRate,
    @@ -1675,7 +1514,7 @@
     //!     }
     //! }
     //!
    -//! # let wallet = doctest_wallet!();
    +//! # let mut wallet = doctest_wallet!();
     //! // create wallet, sync, ...
     //!
     //! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    @@ -1692,28 +1531,21 @@
     
     use crate::types::FeeRate;
     use crate::wallet::utils::IsDust;
    -use crate::{database::Database, WeightedUtxo};
    +use crate::WeightedUtxo;
     use crate::{error::Error, Utxo};
     
    +use alloc::vec::Vec;
     use bitcoin::consensus::encode::serialize;
     use bitcoin::Script;
     
    -#[cfg(test)]
    -use assert_matches::assert_matches;
    +use core::convert::TryInto;
     use rand::seq::SliceRandom;
    -#[cfg(not(test))]
    -use rand::thread_rng;
    -use std::collections::HashMap;
    -use std::convert::TryInto;
     
     /// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
     /// overridden
    -#[cfg(not(test))]
     pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
    -#[cfg(test)]
    -pub type DefaultCoinSelectionAlgorithm = LargestFirstCoinSelection; // make the tests more predictable
     
    -// Base weight of a Txin, not counting the weight needed for satisfying it.
    +// Base weight of a Txin, not counting the weight needed for satisfying it.
     // prev_txid (32 bytes) + prev_vout (4 bytes) + sequence (4 bytes)
     pub(crate) const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4) * 4;
     
    @@ -1773,7 +1605,7 @@
     /// selection algorithm when it creates transactions.
     ///
     /// For an example see [this module](crate::wallet::coin_selection)'s documentation.
    -pub trait CoinSelectionAlgorithm<D: Database>: std::fmt::Debug {
    +pub trait CoinSelectionAlgorithm: core::fmt::Debug {
         /// Perform the coin selection
         ///
         /// - `database`: a reference to the wallet's database that can be used to lookup additional
    @@ -1789,7 +1621,6 @@
         #[allow(clippy::too_many_arguments)]
         fn coin_select(
             &self,
    -        database: &D,
             required_utxos: Vec<WeightedUtxo>,
             optional_utxos: Vec<WeightedUtxo>,
             fee_rate: FeeRate,
    @@ -1805,10 +1636,9 @@
     #[derive(Debug, Default, Clone, Copy)]
     pub struct LargestFirstCoinSelection;
     
    -impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection {
    +impl CoinSelectionAlgorithm for LargestFirstCoinSelection {
         fn coin_select(
             &self,
    -        _database: &D,
             required_utxos: Vec<WeightedUtxo>,
             mut optional_utxos: Vec<WeightedUtxo>,
             fee_rate: FeeRate,
    @@ -1842,46 +1672,22 @@
     #[derive(Debug, Default, Clone, Copy)]
     pub struct OldestFirstCoinSelection;
     
    -impl<D: Database> CoinSelectionAlgorithm<D> for OldestFirstCoinSelection {
    +impl CoinSelectionAlgorithm for OldestFirstCoinSelection {
         fn coin_select(
             &self,
    -        database: &D,
             required_utxos: Vec<WeightedUtxo>,
             mut optional_utxos: Vec<WeightedUtxo>,
             fee_rate: FeeRate,
             target_amount: u64,
             drain_script: &Script,
         ) -> Result<CoinSelectionResult, Error> {
    -        // query db and create a blockheight lookup table
    -        let blockheights = optional_utxos
    -            .iter()
    -            .map(|wu| wu.utxo.outpoint().txid)
    -            // fold is used so we can skip db query for txid that already exist in hashmap acc
    -            .fold(Ok(HashMap::new()), |bh_result_acc, txid| {
    -                bh_result_acc.and_then(|mut bh_acc| {
    -                    if bh_acc.contains_key(&txid) {
    -                        Ok(bh_acc)
    -                    } else {
    -                        database.get_tx(&txid, false).map(|details| {
    -                            bh_acc.insert(
    -                                txid,
    -                                details.and_then(|d| d.confirmation_time.map(|ct| ct.height)),
    -                            );
    -                            bh_acc
    -                        })
    -                    }
    -                })
    -            })?;
    -
             // We put the "required UTXOs" first and make sure the optional UTXOs are sorted from
             // oldest to newest according to blocktime
             // For utxo that doesn't exist in DB, they will have lowest priority to be selected
             let utxos = {
    -            optional_utxos.sort_unstable_by_key(|wu| {
    -                match blockheights.get(&wu.utxo.outpoint().txid) {
    -                    Some(Some(blockheight)) => blockheight,
    -                    _ => &u32::MAX,
    -                }
    +            optional_utxos.sort_unstable_by_key(|wu| match &wu.utxo {
    +                Utxo::Local(local) => Some(local.confirmation_time),
    +                Utxo::Foreign { .. } => None,
                 });
     
                 required_utxos
    @@ -1995,7 +1801,7 @@
     /// Branch and bound coin selection
     ///
     /// Code adapted from Bitcoin Core's implementation and from Mark Erhardt Master's Thesis: <http://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf>
    -#[derive(Debug)]
    +#[derive(Debug, Clone)]
     pub struct BranchAndBoundCoinSelection {
         size_of_change: u64,
     }
    @@ -2018,10 +1824,9 @@
     
     const BNB_TOTAL_TRIES: usize = 100_000;
     
    -impl<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection {
    +impl CoinSelectionAlgorithm for BranchAndBoundCoinSelection {
         fn coin_select(
             &self,
    -        _database: &D,
             required_utxos: Vec<WeightedUtxo>,
             optional_utxos: Vec<WeightedUtxo>,
             fee_rate: FeeRate,
    @@ -2263,16 +2068,7 @@
             drain_script: &Script,
             fee_rate: FeeRate,
         ) -> CoinSelectionResult {
    -        #[cfg(not(test))]
    -        optional_utxos.shuffle(&mut thread_rng());
    -        #[cfg(test)]
    -        {
    -            use rand::{rngs::StdRng, SeedableRng};
    -            let seed = [0; 32];
    -            let mut rng: StdRng = SeedableRng::from_seed(seed);
    -            optional_utxos.shuffle(&mut rng);
    -        }
    -
    +        optional_utxos.shuffle(&mut rand::thread_rng());
             let selected_utxos = optional_utxos.into_iter().fold(
                 (curr_value, vec![]),
                 |(mut amount, mut utxos), utxo| {
    @@ -2318,18 +2114,19 @@
     
     #[cfg(test)]
     mod test {
    -    use std::str::FromStr;
    +    use assert_matches::assert_matches;
    +    use core::str::FromStr;
     
    +    use bdk_chain::ConfirmationTime;
         use bitcoin::{OutPoint, Script, TxOut};
     
         use super::*;
    -    use crate::database::{BatchOperations, MemoryDatabase};
         use crate::types::*;
         use crate::wallet::Vbytes;
     
         use rand::rngs::StdRng;
         use rand::seq::SliceRandom;
    -    use rand::{Rng, SeedableRng};
    +    use rand::{Rng, RngCore, SeedableRng};
     
         // n. of items on witness (1WU) + signature len (1WU) + signature and sighash (72WU)
         // + pubkey len (1WU) + pubkey (33WU) + script sig len (1 byte, 4WU)
    @@ -2337,7 +2134,7 @@
     
         const FEE_AMOUNT: u64 = 50;
     
    -    fn utxo(value: u64, index: u32) -> WeightedUtxo {
    +    fn utxo(value: u64, index: u32, confirmation_time: ConfirmationTime) -> WeightedUtxo {
             assert!(index < 10);
             let outpoint = OutPoint::from_str(&format!(
                 "000000000000000000000000000000000000000000000000000000000000000{}:0",
    @@ -2354,70 +2151,46 @@
                     },
                     keychain: KeychainKind::External,
                     is_spent: false,
    +                derivation_index: 42,
    +                confirmation_time,
                 }),
             }
         }
     
         fn get_test_utxos() -> Vec<WeightedUtxo> {
             vec![
    -            utxo(100_000, 0),
    -            utxo(FEE_AMOUNT as u64 - 40, 1),
    -            utxo(200_000, 2),
    +            utxo(100_000, 0, ConfirmationTime::Unconfirmed),
    +            utxo(FEE_AMOUNT - 40, 1, ConfirmationTime::Unconfirmed),
    +            utxo(200_000, 2, ConfirmationTime::Unconfirmed),
             ]
         }
     
    -    fn setup_database_and_get_oldest_first_test_utxos<D: Database>(
    -        database: &mut D,
    -    ) -> Vec<WeightedUtxo> {
    +    fn get_oldest_first_test_utxos() -> Vec<WeightedUtxo> {
             // ensure utxos are from different tx
    -        let utxo1 = utxo(120_000, 1);
    -        let utxo2 = utxo(80_000, 2);
    -        let utxo3 = utxo(300_000, 3);
    -
    -        // add tx to DB so utxos are sorted by blocktime asc
    -        // utxos will be selected by the following order
    -        // utxo1(blockheight 1) -> utxo2(blockheight 2), utxo3 (blockheight 3)
    -        // timestamp are all set as the same to ensure that only block height is used in sorting
    -        let utxo1_tx_details = TransactionDetails {
    -            transaction: None,
    -            txid: utxo1.utxo.outpoint().txid,
    -            received: 1,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(BlockTime {
    +        let utxo1 = utxo(
    +            120_000,
    +            1,
    +            ConfirmationTime::Confirmed {
                     height: 1,
    -                timestamp: 1231006505,
    -            }),
    -        };
    -
    -        let utxo2_tx_details = TransactionDetails {
    -            transaction: None,
    -            txid: utxo2.utxo.outpoint().txid,
    -            received: 1,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(BlockTime {
    +                time: 1231006505,
    +            },
    +        );
    +        let utxo2 = utxo(
    +            80_000,
    +            2,
    +            ConfirmationTime::Confirmed {
                     height: 2,
    -                timestamp: 1231006505,
    -            }),
    -        };
    -
    -        let utxo3_tx_details = TransactionDetails {
    -            transaction: None,
    -            txid: utxo3.utxo.outpoint().txid,
    -            received: 1,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(BlockTime {
    +                time: 1231006505,
    +            },
    +        );
    +        let utxo3 = utxo(
    +            300_000,
    +            3,
    +            ConfirmationTime::Confirmed {
                     height: 3,
    -                timestamp: 1231006505,
    -            }),
    -        };
    -
    -        database.set_tx(&utxo1_tx_details).unwrap();
    -        database.set_tx(&utxo2_tx_details).unwrap();
    -        database.set_tx(&utxo3_tx_details).unwrap();
    -
    +                time: 1231006505,
    +            },
    +        );
             vec![utxo1, utxo2, utxo3]
         }
     
    @@ -2437,6 +2210,15 @@
                         },
                         keychain: KeychainKind::External,
                         is_spent: false,
    +                    derivation_index: rng.next_u32(),
    +                    confirmation_time: if rng.gen_bool(0.5) {
    +                        ConfirmationTime::Confirmed {
    +                            height: rng.next_u32(),
    +                            time: rng.next_u64(),
    +                        }
    +                    } else {
    +                        ConfirmationTime::Unconfirmed
    +                    },
                     }),
                 });
             }
    @@ -2457,6 +2239,8 @@
                     },
                     keychain: KeychainKind::External,
                     is_spent: false,
    +                derivation_index: 42,
    +                confirmation_time: ConfirmationTime::Unconfirmed,
                 }),
             };
             vec![utxo; utxos_number]
    @@ -2474,13 +2258,11 @@
         #[test]
         fn test_largest_first_coin_selection_success() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 250_000 + FEE_AMOUNT;
     
             let result = LargestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     utxos,
                     vec![],
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2497,13 +2279,11 @@
         #[test]
         fn test_largest_first_coin_selection_use_all() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 20_000 + FEE_AMOUNT;
     
             let result = LargestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     utxos,
                     vec![],
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2520,13 +2300,11 @@
         #[test]
         fn test_largest_first_coin_selection_use_only_necessary() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 20_000 + FEE_AMOUNT;
     
             let result = LargestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2544,13 +2322,11 @@
         #[should_panic(expected = "InsufficientFunds")]
         fn test_largest_first_coin_selection_insufficient_funds() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 500_000 + FEE_AMOUNT;
     
             LargestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2564,13 +2340,11 @@
         #[should_panic(expected = "InsufficientFunds")]
         fn test_largest_first_coin_selection_insufficient_funds_high_fees() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 250_000 + FEE_AMOUNT;
     
             LargestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1000.0),
    @@ -2582,14 +2356,12 @@
     
         #[test]
         fn test_oldest_first_coin_selection_success() {
    -        let mut database = MemoryDatabase::default();
    -        let utxos = setup_database_and_get_oldest_first_test_utxos(&mut database);
    +        let utxos = get_oldest_first_test_utxos();
             let drain_script = Script::default();
             let target_amount = 180_000 + FEE_AMOUNT;
     
             let result = OldestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2603,75 +2375,14 @@
             assert_eq!(result.fee_amount, 136)
         }
     
    -    #[test]
    -    fn test_oldest_first_coin_selection_utxo_not_in_db_will_be_selected_last() {
    -        // ensure utxos are from different tx
    -        let utxo1 = utxo(120_000, 1);
    -        let utxo2 = utxo(80_000, 2);
    -        let utxo3 = utxo(300_000, 3);
    -        let drain_script = Script::default();
    -
    -        let mut database = MemoryDatabase::default();
    -
    -        // add tx to DB so utxos are sorted by blocktime asc
    -        // utxos will be selected by the following order
    -        // utxo1(blockheight 1) -> utxo2(blockheight 2), utxo3 (not exist in DB)
    -        // timestamp are all set as the same to ensure that only block height is used in sorting
    -        let utxo1_tx_details = TransactionDetails {
    -            transaction: None,
    -            txid: utxo1.utxo.outpoint().txid,
    -            received: 1,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(BlockTime {
    -                height: 1,
    -                timestamp: 1231006505,
    -            }),
    -        };
    -
    -        let utxo2_tx_details = TransactionDetails {
    -            transaction: None,
    -            txid: utxo2.utxo.outpoint().txid,
    -            received: 1,
    -            sent: 0,
    -            fee: None,
    -            confirmation_time: Some(BlockTime {
    -                height: 2,
    -                timestamp: 1231006505,
    -            }),
    -        };
    -
    -        database.set_tx(&utxo1_tx_details).unwrap();
    -        database.set_tx(&utxo2_tx_details).unwrap();
    -
    -        let target_amount = 180_000 + FEE_AMOUNT;
    -
    -        let result = OldestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                vec![utxo3, utxo1, utxo2],
    -                FeeRate::from_sat_per_vb(1.0),
    -                target_amount,
    -                &drain_script,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 2);
    -        assert_eq!(result.selected_amount(), 200_000);
    -        assert_eq!(result.fee_amount, 136)
    -    }
    -
         #[test]
         fn test_oldest_first_coin_selection_use_all() {
    -        let mut database = MemoryDatabase::default();
    -        let utxos = setup_database_and_get_oldest_first_test_utxos(&mut database);
    +        let utxos = get_oldest_first_test_utxos();
             let drain_script = Script::default();
             let target_amount = 20_000 + FEE_AMOUNT;
     
             let result = OldestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     utxos,
                     vec![],
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2687,14 +2398,12 @@
     
         #[test]
         fn test_oldest_first_coin_selection_use_only_necessary() {
    -        let mut database = MemoryDatabase::default();
    -        let utxos = setup_database_and_get_oldest_first_test_utxos(&mut database);
    +        let utxos = get_oldest_first_test_utxos();
             let drain_script = Script::default();
             let target_amount = 20_000 + FEE_AMOUNT;
     
             let result = OldestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2711,14 +2420,12 @@
         #[test]
         #[should_panic(expected = "InsufficientFunds")]
         fn test_oldest_first_coin_selection_insufficient_funds() {
    -        let mut database = MemoryDatabase::default();
    -        let utxos = setup_database_and_get_oldest_first_test_utxos(&mut database);
    +        let utxos = get_oldest_first_test_utxos();
             let drain_script = Script::default();
             let target_amount = 600_000 + FEE_AMOUNT;
     
             OldestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2731,15 +2438,13 @@
         #[test]
         #[should_panic(expected = "InsufficientFunds")]
         fn test_oldest_first_coin_selection_insufficient_funds_high_fees() {
    -        let mut database = MemoryDatabase::default();
    -        let utxos = setup_database_and_get_oldest_first_test_utxos(&mut database);
    +        let utxos = get_oldest_first_test_utxos();
     
             let target_amount: u64 = utxos.iter().map(|wu| wu.utxo.txout().value).sum::<u64>() - 50;
             let drain_script = Script::default();
     
             OldestFirstCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1000.0),
    @@ -2755,14 +2460,12 @@
             // select three outputs
             let utxos = generate_same_value_utxos(100_000, 20);
     
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
     
             let target_amount = 250_000 + FEE_AMOUNT;
     
             let result = BranchAndBoundCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2779,13 +2482,11 @@
         #[test]
         fn test_bnb_coin_selection_required_are_enough() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 20_000 + FEE_AMOUNT;
     
             let result = BranchAndBoundCoinSelection::default()
                 .coin_select(
    -                &database,
                     utxos.clone(),
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2802,13 +2503,11 @@
         #[test]
         fn test_bnb_coin_selection_optional_are_enough() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 299756 + FEE_AMOUNT;
     
             let result = BranchAndBoundCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2826,11 +2525,10 @@
         #[ignore]
         fn test_bnb_coin_selection_required_not_enough() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
     
             let required = vec![utxos[0].clone()];
             let mut optional = utxos[1..].to_vec();
    -        optional.push(utxo(500_000, 3));
    +        optional.push(utxo(500_000, 3, ConfirmationTime::Unconfirmed));
     
             // Defensive assertions, for sanity and in case someone changes the test utxos vector.
             let amount: u64 = required.iter().map(|u| u.utxo.txout().value).sum();
    @@ -2843,7 +2541,6 @@
     
             let result = BranchAndBoundCoinSelection::default()
                 .coin_select(
    -                &database,
                     required,
                     optional,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2861,13 +2558,11 @@
         #[should_panic(expected = "InsufficientFunds")]
         fn test_bnb_coin_selection_insufficient_funds() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 500_000 + FEE_AMOUNT;
     
             BranchAndBoundCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2881,13 +2576,11 @@
         #[should_panic(expected = "InsufficientFunds")]
         fn test_bnb_coin_selection_insufficient_funds_high_fees() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 250_000 + FEE_AMOUNT;
     
             BranchAndBoundCoinSelection::default()
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1000.0),
    @@ -2900,13 +2593,11 @@
         #[test]
         fn test_bnb_coin_selection_check_fee_rate() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
             let target_amount = 99932; // first utxo's effective value
     
             let result = BranchAndBoundCoinSelection::new(0)
                 .coin_select(
    -                &database,
                     vec![],
                     utxos,
                     FeeRate::from_sat_per_vb(1.0),
    @@ -2926,7 +2617,6 @@
         fn test_bnb_coin_selection_exact_match() {
             let seed = [0; 32];
             let mut rng: StdRng = SeedableRng::from_seed(seed);
    -        let database = MemoryDatabase::default();
     
             for _i in 0..200 {
                 let mut optional_utxos = generate_random_utxos(&mut rng, 16);
    @@ -2934,7 +2624,6 @@
                 let drain_script = Script::default();
                 let result = BranchAndBoundCoinSelection::new(0)
                     .coin_select(
    -                    &database,
                         vec![],
                         optional_utxos,
                         FeeRate::from_sat_per_vb(0.0),
    @@ -3116,11 +2805,9 @@
         #[test]
         fn test_bnb_exclude_negative_effective_value() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
     
             let selection = BranchAndBoundCoinSelection::default().coin_select(
    -            &database,
                 vec![],
                 utxos,
                 FeeRate::from_sat_per_vb(10.0),
    @@ -3140,7 +2827,6 @@
         #[test]
         fn test_bnb_include_negative_effective_value_when_required() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
     
             let (required, optional) = utxos
    @@ -3148,7 +2834,6 @@
                 .partition(|u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value < 1000));
     
             let selection = BranchAndBoundCoinSelection::default().coin_select(
    -            &database,
                 required,
                 optional,
                 FeeRate::from_sat_per_vb(10.0),
    @@ -3168,11 +2853,9 @@
         #[test]
         fn test_bnb_sum_of_effective_value_negative() {
             let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
             let drain_script = Script::default();
     
             let selection = BranchAndBoundCoinSelection::default().coin_select(
    -            &database,
                 utxos,
                 vec![],
                 FeeRate::from_sat_per_vb(10_000.0),
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html
    index 0ba7466ad6..85a8322d97 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html
    @@ -1,5 +1,4 @@
    -export.rs - source
    1
    +export.rs - source
    1
     2
     3
     4
    @@ -339,48 +338,6 @@
     338
     339
     340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -403,7 +360,6 @@
     //! ```
     //! # use std::str::FromStr;
     //! # use bitcoin::*;
    -//! # use bdk::database::*;
     //! # use bdk::wallet::export::*;
     //! # use bdk::*;
     //! let import = r#"{
    @@ -413,43 +369,39 @@
     //! }"#;
     //!
     //! let import = FullyNodedExport::from_str(import)?;
    -//! let wallet = Wallet::new(
    +//! let wallet = Wallet::new_no_persist(
     //!     &import.descriptor(),
     //!     import.change_descriptor().as_ref(),
     //!     Network::Testnet,
    -//!     MemoryDatabase::default(),
     //! )?;
    -//! # Ok::<_, bdk::Error>(())
    +//! # Ok::<_, Box<dyn std::error::Error>>(())
     //! ```
     //!
     //! ### Export a `Wallet`
     //! ```
     //! # use bitcoin::*;
    -//! # use bdk::database::*;
     //! # use bdk::wallet::export::*;
     //! # use bdk::*;
    -//! let wallet = Wallet::new(
    +//! let wallet = Wallet::new_no_persist(
     //!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
     //!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
     //!     Network::Testnet,
    -//!     MemoryDatabase::default()
     //! )?;
    -//! let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true)
    -//!     .map_err(ToString::to_string)
    -//!     .map_err(bdk::Error::Generic)?;
    +//! let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true).unwrap();
     //!
     //! println!("Exported: {}", export.to_string());
    -//! # Ok::<_, bdk::Error>(())
    +//! # Ok::<_, Box<dyn std::error::Error>>(())
     //! ```
     
    -use std::str::FromStr;
    +use core::str::FromStr;
     
    +use alloc::string::{String, ToString};
    +use bdk_chain::sparse_chain::ChainPosition;
     use serde::{Deserialize, Serialize};
     
     use miniscript::descriptor::{ShInner, WshInner};
     use miniscript::{Descriptor, ScriptContext, Terminal};
     
    -use crate::database::BatchDatabase;
     use crate::types::KeychainKind;
     use crate::wallet::Wallet;
     
    @@ -499,7 +451,7 @@
         ///
         /// If the database is empty or `include_blockheight` is false, the `blockheight` field
         /// returned will be `0`.
    -    pub fn export_wallet<D: BatchDatabase>(
    +    pub fn export_wallet<D>(
             wallet: &Wallet<D>,
             label: &str,
             include_blockheight: bool,
    @@ -514,15 +466,15 @@
             let descriptor = remove_checksum(descriptor);
             Self::is_compatible_with_core(&descriptor)?;
     
    -        let blockheight = match wallet.database.borrow().iter_txs(false) {
    -            _ if !include_blockheight => 0,
    -            Err(_) => 0,
    -            Ok(txs) => txs
    -                .into_iter()
    -                .filter_map(|tx| tx.confirmation_time.map(|c| c.height))
    -                .min()
    -                .unwrap_or(0),
    -        };
    +        let blockheight = if include_blockheight {
    +            wallet
    +                .transactions()
    +                .next()
    +                .and_then(|(pos, _)| pos.height().into())
    +                .unwrap_or(0)
    +        } else {
    +            0
    +        };
     
             let export = FullyNodedExport {
                 descriptor,
    @@ -530,11 +482,7 @@
                 blockheight,
             };
     
    -        let change_descriptor = match wallet
    -            .public_descriptor(KeychainKind::Internal)
    -            .map_err(|_| "Invalid change descriptor")?
    -            .is_some()
    -        {
    +        let change_descriptor = match wallet.public_descriptor(KeychainKind::Internal).is_some() {
                 false => None,
                 true => {
                     let descriptor = wallet
    @@ -604,52 +552,43 @@
     
     #[cfg(test)]
     mod test {
    -    use std::str::FromStr;
    +    use core::str::FromStr;
     
    -    use bitcoin::{Network, Txid};
    +    use bdk_chain::{BlockId, ConfirmationTime};
    +    use bitcoin::hashes::Hash;
    +    use bitcoin::{BlockHash, Network, Transaction};
     
         use super::*;
    -    use crate::database::{memory::MemoryDatabase, BatchOperations};
    -    use crate::types::TransactionDetails;
         use crate::wallet::Wallet;
    -    use crate::BlockTime;
    -
    -    fn get_test_db() -> MemoryDatabase {
    -        let mut db = MemoryDatabase::new();
    -        db.set_tx(&TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_str(
    -                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
    -            )
    -            .unwrap(),
     
    -            received: 100_000,
    -            sent: 0,
    -            fee: Some(500),
    -            confirmation_time: Some(BlockTime {
    -                timestamp: 12345678,
    +    fn get_test_wallet(
    +        descriptor: &str,
    +        change_descriptor: Option<&str>,
    +        network: Network,
    +    ) -> Wallet<()> {
    +        let mut wallet = Wallet::new_no_persist(descriptor, change_descriptor, network).unwrap();
    +        let transaction = Transaction {
    +            input: vec![],
    +            output: vec![],
    +            version: 0,
    +            lock_time: bitcoin::PackedLockTime::ZERO,
    +        };
    +        wallet
    +            .insert_checkpoint(BlockId {
                     height: 5001,
    -            }),
    -        })
    -        .unwrap();
    -
    -        db.set_tx(&TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_str(
    -                "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    +                hash: BlockHash::all_zeros(),
    +            })
    +            .unwrap();
    +        wallet
    +            .insert_tx(
    +                transaction,
    +                ConfirmationTime::Confirmed {
    +                    height: 5000,
    +                    time: 0,
    +                },
                 )
    -            .unwrap(),
    -            received: 25_000,
    -            sent: 0,
    -            fee: Some(300),
    -            confirmation_time: Some(BlockTime {
    -                timestamp: 12345677,
    -                height: 5000,
    -            }),
    -        })
    -        .unwrap();
    -
    -        db
    +            .unwrap();
    +        wallet
         }
     
         #[test]
    @@ -657,13 +596,7 @@
             let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
             let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
     
    -        let wallet = Wallet::new(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    +        let wallet = get_test_wallet(descriptor, Some(change_descriptor), Network::Bitcoin);
             let export = FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
     
             assert_eq!(export.descriptor(), descriptor);
    @@ -681,7 +614,7 @@
     
             let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
     
    -        let wallet = Wallet::new(descriptor, None, Network::Bitcoin, get_test_db()).unwrap();
    +        let wallet = get_test_wallet(descriptor, None, Network::Bitcoin);
             FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
         }
     
    @@ -694,13 +627,7 @@
             let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
             let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/50'/0'/1/*)";
     
    -        let wallet = Wallet::new(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    +        let wallet = get_test_wallet(descriptor, Some(change_descriptor), Network::Bitcoin);
             FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
         }
     
    @@ -717,13 +644,7 @@
                                            [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/1/*\
                                      ))";
     
    -        let wallet = Wallet::new(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Testnet,
    -            get_test_db(),
    -        )
    -        .unwrap();
    +        let wallet = get_test_wallet(descriptor, Some(change_descriptor), Network::Testnet);
             let export = FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
     
             assert_eq!(export.descriptor(), descriptor);
    @@ -737,13 +658,7 @@
             let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
             let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
     
    -        let wallet = Wallet::new(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    +        let wallet = get_test_wallet(descriptor, Some(change_descriptor), Network::Bitcoin);
             let export = FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
     
             assert_eq!(export.to_string(), "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}");
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/hardwaresigner.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/hardwaresigner.rs.html
    deleted file mode 100644
    index 134e77ab46..0000000000
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/hardwaresigner.rs.html
    +++ /dev/null
    @@ -1,203 +0,0 @@
    -hardwaresigner.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! HWI Signer
    -//!
    -//! This module contains HWISigner, an implementation of a [TransactionSigner] to be
    -//! used with hardware wallets.
    -//! ```no_run
    -//! # use bdk::bitcoin::Network;
    -//! # use bdk::database::MemoryDatabase;
    -//! # use bdk::signer::SignerOrdering;
    -//! # use bdk::wallet::hardwaresigner::HWISigner;
    -//! # use bdk::wallet::AddressIndex::New;
    -//! # use bdk::{FeeRate, KeychainKind, SignOptions, SyncOptions, Wallet};
    -//! # use hwi::{types::HWIChain, HWIClient};
    -//! # use std::sync::Arc;
    -//! #
    -//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
    -//! let mut devices = HWIClient::enumerate()?;
    -//! if devices.is_empty() {
    -//!     panic!("No devices found!");
    -//! }
    -//! let first_device = devices.remove(0)?;
    -//! let custom_signer = HWISigner::from_device(&first_device, HWIChain::Test)?;
    -//!
    -//! # let mut wallet = Wallet::new(
    -//! #     "",
    -//! #     None,
    -//! #     Network::Testnet,
    -//! #     MemoryDatabase::default(),
    -//! # )?;
    -//! #
    -//! // Adding the hardware signer to the BDK wallet
    -//! wallet.add_signer(
    -//!     KeychainKind::External,
    -//!     SignerOrdering(200),
    -//!     Arc::new(custom_signer),
    -//! );
    -//!
    -//! # Ok(())
    -//! # }
    -//! ```
    -
    -use bitcoin::psbt::PartiallySignedTransaction;
    -use bitcoin::secp256k1::{All, Secp256k1};
    -use bitcoin::util::bip32::Fingerprint;
    -
    -use hwi::error::Error;
    -use hwi::types::{HWIChain, HWIDevice};
    -use hwi::HWIClient;
    -
    -use crate::signer::{SignerCommon, SignerError, SignerId, TransactionSigner};
    -
    -#[derive(Debug)]
    -/// Custom signer for Hardware Wallets
    -///
    -/// This ignores `sign_options` and leaves the decisions up to the hardware wallet.
    -pub struct HWISigner {
    -    fingerprint: Fingerprint,
    -    client: HWIClient,
    -}
    -
    -impl HWISigner {
    -    /// Create a instance from the specified device and chain
    -    pub fn from_device(device: &HWIDevice, chain: HWIChain) -> Result<HWISigner, Error> {
    -        let client = HWIClient::get_client(device, false, chain)?;
    -        Ok(HWISigner {
    -            fingerprint: device.fingerprint,
    -            client,
    -        })
    -    }
    -}
    -
    -impl SignerCommon for HWISigner {
    -    fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
    -        SignerId::Fingerprint(self.fingerprint)
    -    }
    -}
    -
    -/// This implementation ignores `sign_options`
    -impl TransactionSigner for HWISigner {
    -    fn sign_transaction(
    -        &self,
    -        psbt: &mut PartiallySignedTransaction,
    -        _sign_options: &crate::SignOptions,
    -        _secp: &crate::wallet::utils::SecpCtx,
    -    ) -> Result<(), SignerError> {
    -        psbt.combine(self.client.sign_tx(psbt)?.psbt)
    -            .expect("Failed to combine HW signed psbt with passed PSBT");
    -        Ok(())
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html index de76a477ff..4fd84d2e2c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html @@ -1,5 +1,4 @@ -mod.rs - source
    1
    +mod.rs - source
    1
     2
     3
     4
    @@ -1802,3774 +1801,6 @@
     1801
     1802
     1803
    -1804
    -1805
    -1806
    -1807
    -1808
    -1809
    -1810
    -1811
    -1812
    -1813
    -1814
    -1815
    -1816
    -1817
    -1818
    -1819
    -1820
    -1821
    -1822
    -1823
    -1824
    -1825
    -1826
    -1827
    -1828
    -1829
    -1830
    -1831
    -1832
    -1833
    -1834
    -1835
    -1836
    -1837
    -1838
    -1839
    -1840
    -1841
    -1842
    -1843
    -1844
    -1845
    -1846
    -1847
    -1848
    -1849
    -1850
    -1851
    -1852
    -1853
    -1854
    -1855
    -1856
    -1857
    -1858
    -1859
    -1860
    -1861
    -1862
    -1863
    -1864
    -1865
    -1866
    -1867
    -1868
    -1869
    -1870
    -1871
    -1872
    -1873
    -1874
    -1875
    -1876
    -1877
    -1878
    -1879
    -1880
    -1881
    -1882
    -1883
    -1884
    -1885
    -1886
    -1887
    -1888
    -1889
    -1890
    -1891
    -1892
    -1893
    -1894
    -1895
    -1896
    -1897
    -1898
    -1899
    -1900
    -1901
    -1902
    -1903
    -1904
    -1905
    -1906
    -1907
    -1908
    -1909
    -1910
    -1911
    -1912
    -1913
    -1914
    -1915
    -1916
    -1917
    -1918
    -1919
    -1920
    -1921
    -1922
    -1923
    -1924
    -1925
    -1926
    -1927
    -1928
    -1929
    -1930
    -1931
    -1932
    -1933
    -1934
    -1935
    -1936
    -1937
    -1938
    -1939
    -1940
    -1941
    -1942
    -1943
    -1944
    -1945
    -1946
    -1947
    -1948
    -1949
    -1950
    -1951
    -1952
    -1953
    -1954
    -1955
    -1956
    -1957
    -1958
    -1959
    -1960
    -1961
    -1962
    -1963
    -1964
    -1965
    -1966
    -1967
    -1968
    -1969
    -1970
    -1971
    -1972
    -1973
    -1974
    -1975
    -1976
    -1977
    -1978
    -1979
    -1980
    -1981
    -1982
    -1983
    -1984
    -1985
    -1986
    -1987
    -1988
    -1989
    -1990
    -1991
    -1992
    -1993
    -1994
    -1995
    -1996
    -1997
    -1998
    -1999
    -2000
    -2001
    -2002
    -2003
    -2004
    -2005
    -2006
    -2007
    -2008
    -2009
    -2010
    -2011
    -2012
    -2013
    -2014
    -2015
    -2016
    -2017
    -2018
    -2019
    -2020
    -2021
    -2022
    -2023
    -2024
    -2025
    -2026
    -2027
    -2028
    -2029
    -2030
    -2031
    -2032
    -2033
    -2034
    -2035
    -2036
    -2037
    -2038
    -2039
    -2040
    -2041
    -2042
    -2043
    -2044
    -2045
    -2046
    -2047
    -2048
    -2049
    -2050
    -2051
    -2052
    -2053
    -2054
    -2055
    -2056
    -2057
    -2058
    -2059
    -2060
    -2061
    -2062
    -2063
    -2064
    -2065
    -2066
    -2067
    -2068
    -2069
    -2070
    -2071
    -2072
    -2073
    -2074
    -2075
    -2076
    -2077
    -2078
    -2079
    -2080
    -2081
    -2082
    -2083
    -2084
    -2085
    -2086
    -2087
    -2088
    -2089
    -2090
    -2091
    -2092
    -2093
    -2094
    -2095
    -2096
    -2097
    -2098
    -2099
    -2100
    -2101
    -2102
    -2103
    -2104
    -2105
    -2106
    -2107
    -2108
    -2109
    -2110
    -2111
    -2112
    -2113
    -2114
    -2115
    -2116
    -2117
    -2118
    -2119
    -2120
    -2121
    -2122
    -2123
    -2124
    -2125
    -2126
    -2127
    -2128
    -2129
    -2130
    -2131
    -2132
    -2133
    -2134
    -2135
    -2136
    -2137
    -2138
    -2139
    -2140
    -2141
    -2142
    -2143
    -2144
    -2145
    -2146
    -2147
    -2148
    -2149
    -2150
    -2151
    -2152
    -2153
    -2154
    -2155
    -2156
    -2157
    -2158
    -2159
    -2160
    -2161
    -2162
    -2163
    -2164
    -2165
    -2166
    -2167
    -2168
    -2169
    -2170
    -2171
    -2172
    -2173
    -2174
    -2175
    -2176
    -2177
    -2178
    -2179
    -2180
    -2181
    -2182
    -2183
    -2184
    -2185
    -2186
    -2187
    -2188
    -2189
    -2190
    -2191
    -2192
    -2193
    -2194
    -2195
    -2196
    -2197
    -2198
    -2199
    -2200
    -2201
    -2202
    -2203
    -2204
    -2205
    -2206
    -2207
    -2208
    -2209
    -2210
    -2211
    -2212
    -2213
    -2214
    -2215
    -2216
    -2217
    -2218
    -2219
    -2220
    -2221
    -2222
    -2223
    -2224
    -2225
    -2226
    -2227
    -2228
    -2229
    -2230
    -2231
    -2232
    -2233
    -2234
    -2235
    -2236
    -2237
    -2238
    -2239
    -2240
    -2241
    -2242
    -2243
    -2244
    -2245
    -2246
    -2247
    -2248
    -2249
    -2250
    -2251
    -2252
    -2253
    -2254
    -2255
    -2256
    -2257
    -2258
    -2259
    -2260
    -2261
    -2262
    -2263
    -2264
    -2265
    -2266
    -2267
    -2268
    -2269
    -2270
    -2271
    -2272
    -2273
    -2274
    -2275
    -2276
    -2277
    -2278
    -2279
    -2280
    -2281
    -2282
    -2283
    -2284
    -2285
    -2286
    -2287
    -2288
    -2289
    -2290
    -2291
    -2292
    -2293
    -2294
    -2295
    -2296
    -2297
    -2298
    -2299
    -2300
    -2301
    -2302
    -2303
    -2304
    -2305
    -2306
    -2307
    -2308
    -2309
    -2310
    -2311
    -2312
    -2313
    -2314
    -2315
    -2316
    -2317
    -2318
    -2319
    -2320
    -2321
    -2322
    -2323
    -2324
    -2325
    -2326
    -2327
    -2328
    -2329
    -2330
    -2331
    -2332
    -2333
    -2334
    -2335
    -2336
    -2337
    -2338
    -2339
    -2340
    -2341
    -2342
    -2343
    -2344
    -2345
    -2346
    -2347
    -2348
    -2349
    -2350
    -2351
    -2352
    -2353
    -2354
    -2355
    -2356
    -2357
    -2358
    -2359
    -2360
    -2361
    -2362
    -2363
    -2364
    -2365
    -2366
    -2367
    -2368
    -2369
    -2370
    -2371
    -2372
    -2373
    -2374
    -2375
    -2376
    -2377
    -2378
    -2379
    -2380
    -2381
    -2382
    -2383
    -2384
    -2385
    -2386
    -2387
    -2388
    -2389
    -2390
    -2391
    -2392
    -2393
    -2394
    -2395
    -2396
    -2397
    -2398
    -2399
    -2400
    -2401
    -2402
    -2403
    -2404
    -2405
    -2406
    -2407
    -2408
    -2409
    -2410
    -2411
    -2412
    -2413
    -2414
    -2415
    -2416
    -2417
    -2418
    -2419
    -2420
    -2421
    -2422
    -2423
    -2424
    -2425
    -2426
    -2427
    -2428
    -2429
    -2430
    -2431
    -2432
    -2433
    -2434
    -2435
    -2436
    -2437
    -2438
    -2439
    -2440
    -2441
    -2442
    -2443
    -2444
    -2445
    -2446
    -2447
    -2448
    -2449
    -2450
    -2451
    -2452
    -2453
    -2454
    -2455
    -2456
    -2457
    -2458
    -2459
    -2460
    -2461
    -2462
    -2463
    -2464
    -2465
    -2466
    -2467
    -2468
    -2469
    -2470
    -2471
    -2472
    -2473
    -2474
    -2475
    -2476
    -2477
    -2478
    -2479
    -2480
    -2481
    -2482
    -2483
    -2484
    -2485
    -2486
    -2487
    -2488
    -2489
    -2490
    -2491
    -2492
    -2493
    -2494
    -2495
    -2496
    -2497
    -2498
    -2499
    -2500
    -2501
    -2502
    -2503
    -2504
    -2505
    -2506
    -2507
    -2508
    -2509
    -2510
    -2511
    -2512
    -2513
    -2514
    -2515
    -2516
    -2517
    -2518
    -2519
    -2520
    -2521
    -2522
    -2523
    -2524
    -2525
    -2526
    -2527
    -2528
    -2529
    -2530
    -2531
    -2532
    -2533
    -2534
    -2535
    -2536
    -2537
    -2538
    -2539
    -2540
    -2541
    -2542
    -2543
    -2544
    -2545
    -2546
    -2547
    -2548
    -2549
    -2550
    -2551
    -2552
    -2553
    -2554
    -2555
    -2556
    -2557
    -2558
    -2559
    -2560
    -2561
    -2562
    -2563
    -2564
    -2565
    -2566
    -2567
    -2568
    -2569
    -2570
    -2571
    -2572
    -2573
    -2574
    -2575
    -2576
    -2577
    -2578
    -2579
    -2580
    -2581
    -2582
    -2583
    -2584
    -2585
    -2586
    -2587
    -2588
    -2589
    -2590
    -2591
    -2592
    -2593
    -2594
    -2595
    -2596
    -2597
    -2598
    -2599
    -2600
    -2601
    -2602
    -2603
    -2604
    -2605
    -2606
    -2607
    -2608
    -2609
    -2610
    -2611
    -2612
    -2613
    -2614
    -2615
    -2616
    -2617
    -2618
    -2619
    -2620
    -2621
    -2622
    -2623
    -2624
    -2625
    -2626
    -2627
    -2628
    -2629
    -2630
    -2631
    -2632
    -2633
    -2634
    -2635
    -2636
    -2637
    -2638
    -2639
    -2640
    -2641
    -2642
    -2643
    -2644
    -2645
    -2646
    -2647
    -2648
    -2649
    -2650
    -2651
    -2652
    -2653
    -2654
    -2655
    -2656
    -2657
    -2658
    -2659
    -2660
    -2661
    -2662
    -2663
    -2664
    -2665
    -2666
    -2667
    -2668
    -2669
    -2670
    -2671
    -2672
    -2673
    -2674
    -2675
    -2676
    -2677
    -2678
    -2679
    -2680
    -2681
    -2682
    -2683
    -2684
    -2685
    -2686
    -2687
    -2688
    -2689
    -2690
    -2691
    -2692
    -2693
    -2694
    -2695
    -2696
    -2697
    -2698
    -2699
    -2700
    -2701
    -2702
    -2703
    -2704
    -2705
    -2706
    -2707
    -2708
    -2709
    -2710
    -2711
    -2712
    -2713
    -2714
    -2715
    -2716
    -2717
    -2718
    -2719
    -2720
    -2721
    -2722
    -2723
    -2724
    -2725
    -2726
    -2727
    -2728
    -2729
    -2730
    -2731
    -2732
    -2733
    -2734
    -2735
    -2736
    -2737
    -2738
    -2739
    -2740
    -2741
    -2742
    -2743
    -2744
    -2745
    -2746
    -2747
    -2748
    -2749
    -2750
    -2751
    -2752
    -2753
    -2754
    -2755
    -2756
    -2757
    -2758
    -2759
    -2760
    -2761
    -2762
    -2763
    -2764
    -2765
    -2766
    -2767
    -2768
    -2769
    -2770
    -2771
    -2772
    -2773
    -2774
    -2775
    -2776
    -2777
    -2778
    -2779
    -2780
    -2781
    -2782
    -2783
    -2784
    -2785
    -2786
    -2787
    -2788
    -2789
    -2790
    -2791
    -2792
    -2793
    -2794
    -2795
    -2796
    -2797
    -2798
    -2799
    -2800
    -2801
    -2802
    -2803
    -2804
    -2805
    -2806
    -2807
    -2808
    -2809
    -2810
    -2811
    -2812
    -2813
    -2814
    -2815
    -2816
    -2817
    -2818
    -2819
    -2820
    -2821
    -2822
    -2823
    -2824
    -2825
    -2826
    -2827
    -2828
    -2829
    -2830
    -2831
    -2832
    -2833
    -2834
    -2835
    -2836
    -2837
    -2838
    -2839
    -2840
    -2841
    -2842
    -2843
    -2844
    -2845
    -2846
    -2847
    -2848
    -2849
    -2850
    -2851
    -2852
    -2853
    -2854
    -2855
    -2856
    -2857
    -2858
    -2859
    -2860
    -2861
    -2862
    -2863
    -2864
    -2865
    -2866
    -2867
    -2868
    -2869
    -2870
    -2871
    -2872
    -2873
    -2874
    -2875
    -2876
    -2877
    -2878
    -2879
    -2880
    -2881
    -2882
    -2883
    -2884
    -2885
    -2886
    -2887
    -2888
    -2889
    -2890
    -2891
    -2892
    -2893
    -2894
    -2895
    -2896
    -2897
    -2898
    -2899
    -2900
    -2901
    -2902
    -2903
    -2904
    -2905
    -2906
    -2907
    -2908
    -2909
    -2910
    -2911
    -2912
    -2913
    -2914
    -2915
    -2916
    -2917
    -2918
    -2919
    -2920
    -2921
    -2922
    -2923
    -2924
    -2925
    -2926
    -2927
    -2928
    -2929
    -2930
    -2931
    -2932
    -2933
    -2934
    -2935
    -2936
    -2937
    -2938
    -2939
    -2940
    -2941
    -2942
    -2943
    -2944
    -2945
    -2946
    -2947
    -2948
    -2949
    -2950
    -2951
    -2952
    -2953
    -2954
    -2955
    -2956
    -2957
    -2958
    -2959
    -2960
    -2961
    -2962
    -2963
    -2964
    -2965
    -2966
    -2967
    -2968
    -2969
    -2970
    -2971
    -2972
    -2973
    -2974
    -2975
    -2976
    -2977
    -2978
    -2979
    -2980
    -2981
    -2982
    -2983
    -2984
    -2985
    -2986
    -2987
    -2988
    -2989
    -2990
    -2991
    -2992
    -2993
    -2994
    -2995
    -2996
    -2997
    -2998
    -2999
    -3000
    -3001
    -3002
    -3003
    -3004
    -3005
    -3006
    -3007
    -3008
    -3009
    -3010
    -3011
    -3012
    -3013
    -3014
    -3015
    -3016
    -3017
    -3018
    -3019
    -3020
    -3021
    -3022
    -3023
    -3024
    -3025
    -3026
    -3027
    -3028
    -3029
    -3030
    -3031
    -3032
    -3033
    -3034
    -3035
    -3036
    -3037
    -3038
    -3039
    -3040
    -3041
    -3042
    -3043
    -3044
    -3045
    -3046
    -3047
    -3048
    -3049
    -3050
    -3051
    -3052
    -3053
    -3054
    -3055
    -3056
    -3057
    -3058
    -3059
    -3060
    -3061
    -3062
    -3063
    -3064
    -3065
    -3066
    -3067
    -3068
    -3069
    -3070
    -3071
    -3072
    -3073
    -3074
    -3075
    -3076
    -3077
    -3078
    -3079
    -3080
    -3081
    -3082
    -3083
    -3084
    -3085
    -3086
    -3087
    -3088
    -3089
    -3090
    -3091
    -3092
    -3093
    -3094
    -3095
    -3096
    -3097
    -3098
    -3099
    -3100
    -3101
    -3102
    -3103
    -3104
    -3105
    -3106
    -3107
    -3108
    -3109
    -3110
    -3111
    -3112
    -3113
    -3114
    -3115
    -3116
    -3117
    -3118
    -3119
    -3120
    -3121
    -3122
    -3123
    -3124
    -3125
    -3126
    -3127
    -3128
    -3129
    -3130
    -3131
    -3132
    -3133
    -3134
    -3135
    -3136
    -3137
    -3138
    -3139
    -3140
    -3141
    -3142
    -3143
    -3144
    -3145
    -3146
    -3147
    -3148
    -3149
    -3150
    -3151
    -3152
    -3153
    -3154
    -3155
    -3156
    -3157
    -3158
    -3159
    -3160
    -3161
    -3162
    -3163
    -3164
    -3165
    -3166
    -3167
    -3168
    -3169
    -3170
    -3171
    -3172
    -3173
    -3174
    -3175
    -3176
    -3177
    -3178
    -3179
    -3180
    -3181
    -3182
    -3183
    -3184
    -3185
    -3186
    -3187
    -3188
    -3189
    -3190
    -3191
    -3192
    -3193
    -3194
    -3195
    -3196
    -3197
    -3198
    -3199
    -3200
    -3201
    -3202
    -3203
    -3204
    -3205
    -3206
    -3207
    -3208
    -3209
    -3210
    -3211
    -3212
    -3213
    -3214
    -3215
    -3216
    -3217
    -3218
    -3219
    -3220
    -3221
    -3222
    -3223
    -3224
    -3225
    -3226
    -3227
    -3228
    -3229
    -3230
    -3231
    -3232
    -3233
    -3234
    -3235
    -3236
    -3237
    -3238
    -3239
    -3240
    -3241
    -3242
    -3243
    -3244
    -3245
    -3246
    -3247
    -3248
    -3249
    -3250
    -3251
    -3252
    -3253
    -3254
    -3255
    -3256
    -3257
    -3258
    -3259
    -3260
    -3261
    -3262
    -3263
    -3264
    -3265
    -3266
    -3267
    -3268
    -3269
    -3270
    -3271
    -3272
    -3273
    -3274
    -3275
    -3276
    -3277
    -3278
    -3279
    -3280
    -3281
    -3282
    -3283
    -3284
    -3285
    -3286
    -3287
    -3288
    -3289
    -3290
    -3291
    -3292
    -3293
    -3294
    -3295
    -3296
    -3297
    -3298
    -3299
    -3300
    -3301
    -3302
    -3303
    -3304
    -3305
    -3306
    -3307
    -3308
    -3309
    -3310
    -3311
    -3312
    -3313
    -3314
    -3315
    -3316
    -3317
    -3318
    -3319
    -3320
    -3321
    -3322
    -3323
    -3324
    -3325
    -3326
    -3327
    -3328
    -3329
    -3330
    -3331
    -3332
    -3333
    -3334
    -3335
    -3336
    -3337
    -3338
    -3339
    -3340
    -3341
    -3342
    -3343
    -3344
    -3345
    -3346
    -3347
    -3348
    -3349
    -3350
    -3351
    -3352
    -3353
    -3354
    -3355
    -3356
    -3357
    -3358
    -3359
    -3360
    -3361
    -3362
    -3363
    -3364
    -3365
    -3366
    -3367
    -3368
    -3369
    -3370
    -3371
    -3372
    -3373
    -3374
    -3375
    -3376
    -3377
    -3378
    -3379
    -3380
    -3381
    -3382
    -3383
    -3384
    -3385
    -3386
    -3387
    -3388
    -3389
    -3390
    -3391
    -3392
    -3393
    -3394
    -3395
    -3396
    -3397
    -3398
    -3399
    -3400
    -3401
    -3402
    -3403
    -3404
    -3405
    -3406
    -3407
    -3408
    -3409
    -3410
    -3411
    -3412
    -3413
    -3414
    -3415
    -3416
    -3417
    -3418
    -3419
    -3420
    -3421
    -3422
    -3423
    -3424
    -3425
    -3426
    -3427
    -3428
    -3429
    -3430
    -3431
    -3432
    -3433
    -3434
    -3435
    -3436
    -3437
    -3438
    -3439
    -3440
    -3441
    -3442
    -3443
    -3444
    -3445
    -3446
    -3447
    -3448
    -3449
    -3450
    -3451
    -3452
    -3453
    -3454
    -3455
    -3456
    -3457
    -3458
    -3459
    -3460
    -3461
    -3462
    -3463
    -3464
    -3465
    -3466
    -3467
    -3468
    -3469
    -3470
    -3471
    -3472
    -3473
    -3474
    -3475
    -3476
    -3477
    -3478
    -3479
    -3480
    -3481
    -3482
    -3483
    -3484
    -3485
    -3486
    -3487
    -3488
    -3489
    -3490
    -3491
    -3492
    -3493
    -3494
    -3495
    -3496
    -3497
    -3498
    -3499
    -3500
    -3501
    -3502
    -3503
    -3504
    -3505
    -3506
    -3507
    -3508
    -3509
    -3510
    -3511
    -3512
    -3513
    -3514
    -3515
    -3516
    -3517
    -3518
    -3519
    -3520
    -3521
    -3522
    -3523
    -3524
    -3525
    -3526
    -3527
    -3528
    -3529
    -3530
    -3531
    -3532
    -3533
    -3534
    -3535
    -3536
    -3537
    -3538
    -3539
    -3540
    -3541
    -3542
    -3543
    -3544
    -3545
    -3546
    -3547
    -3548
    -3549
    -3550
    -3551
    -3552
    -3553
    -3554
    -3555
    -3556
    -3557
    -3558
    -3559
    -3560
    -3561
    -3562
    -3563
    -3564
    -3565
    -3566
    -3567
    -3568
    -3569
    -3570
    -3571
    -3572
    -3573
    -3574
    -3575
    -3576
    -3577
    -3578
    -3579
    -3580
    -3581
    -3582
    -3583
    -3584
    -3585
    -3586
    -3587
    -3588
    -3589
    -3590
    -3591
    -3592
    -3593
    -3594
    -3595
    -3596
    -3597
    -3598
    -3599
    -3600
    -3601
    -3602
    -3603
    -3604
    -3605
    -3606
    -3607
    -3608
    -3609
    -3610
    -3611
    -3612
    -3613
    -3614
    -3615
    -3616
    -3617
    -3618
    -3619
    -3620
    -3621
    -3622
    -3623
    -3624
    -3625
    -3626
    -3627
    -3628
    -3629
    -3630
    -3631
    -3632
    -3633
    -3634
    -3635
    -3636
    -3637
    -3638
    -3639
    -3640
    -3641
    -3642
    -3643
    -3644
    -3645
    -3646
    -3647
    -3648
    -3649
    -3650
    -3651
    -3652
    -3653
    -3654
    -3655
    -3656
    -3657
    -3658
    -3659
    -3660
    -3661
    -3662
    -3663
    -3664
    -3665
    -3666
    -3667
    -3668
    -3669
    -3670
    -3671
    -3672
    -3673
    -3674
    -3675
    -3676
    -3677
    -3678
    -3679
    -3680
    -3681
    -3682
    -3683
    -3684
    -3685
    -3686
    -3687
    -3688
    -3689
    -3690
    -3691
    -3692
    -3693
    -3694
    -3695
    -3696
    -3697
    -3698
    -3699
    -3700
    -3701
    -3702
    -3703
    -3704
    -3705
    -3706
    -3707
    -3708
    -3709
    -3710
    -3711
    -3712
    -3713
    -3714
    -3715
    -3716
    -3717
    -3718
    -3719
    -3720
    -3721
    -3722
    -3723
    -3724
    -3725
    -3726
    -3727
    -3728
    -3729
    -3730
    -3731
    -3732
    -3733
    -3734
    -3735
    -3736
    -3737
    -3738
    -3739
    -3740
    -3741
    -3742
    -3743
    -3744
    -3745
    -3746
    -3747
    -3748
    -3749
    -3750
    -3751
    -3752
    -3753
    -3754
    -3755
    -3756
    -3757
    -3758
    -3759
    -3760
    -3761
    -3762
    -3763
    -3764
    -3765
    -3766
    -3767
    -3768
    -3769
    -3770
    -3771
    -3772
    -3773
    -3774
    -3775
    -3776
    -3777
    -3778
    -3779
    -3780
    -3781
    -3782
    -3783
    -3784
    -3785
    -3786
    -3787
    -3788
    -3789
    -3790
    -3791
    -3792
    -3793
    -3794
    -3795
    -3796
    -3797
    -3798
    -3799
    -3800
    -3801
    -3802
    -3803
    -3804
    -3805
    -3806
    -3807
    -3808
    -3809
    -3810
    -3811
    -3812
    -3813
    -3814
    -3815
    -3816
    -3817
    -3818
    -3819
    -3820
    -3821
    -3822
    -3823
    -3824
    -3825
    -3826
    -3827
    -3828
    -3829
    -3830
    -3831
    -3832
    -3833
    -3834
    -3835
    -3836
    -3837
    -3838
    -3839
    -3840
    -3841
    -3842
    -3843
    -3844
    -3845
    -3846
    -3847
    -3848
    -3849
    -3850
    -3851
    -3852
    -3853
    -3854
    -3855
    -3856
    -3857
    -3858
    -3859
    -3860
    -3861
    -3862
    -3863
    -3864
    -3865
    -3866
    -3867
    -3868
    -3869
    -3870
    -3871
    -3872
    -3873
    -3874
    -3875
    -3876
    -3877
    -3878
    -3879
    -3880
    -3881
    -3882
    -3883
    -3884
    -3885
    -3886
    -3887
    -3888
    -3889
    -3890
    -3891
    -3892
    -3893
    -3894
    -3895
    -3896
    -3897
    -3898
    -3899
    -3900
    -3901
    -3902
    -3903
    -3904
    -3905
    -3906
    -3907
    -3908
    -3909
    -3910
    -3911
    -3912
    -3913
    -3914
    -3915
    -3916
    -3917
    -3918
    -3919
    -3920
    -3921
    -3922
    -3923
    -3924
    -3925
    -3926
    -3927
    -3928
    -3929
    -3930
    -3931
    -3932
    -3933
    -3934
    -3935
    -3936
    -3937
    -3938
    -3939
    -3940
    -3941
    -3942
    -3943
    -3944
    -3945
    -3946
    -3947
    -3948
    -3949
    -3950
    -3951
    -3952
    -3953
    -3954
    -3955
    -3956
    -3957
    -3958
    -3959
    -3960
    -3961
    -3962
    -3963
    -3964
    -3965
    -3966
    -3967
    -3968
    -3969
    -3970
    -3971
    -3972
    -3973
    -3974
    -3975
    -3976
    -3977
    -3978
    -3979
    -3980
    -3981
    -3982
    -3983
    -3984
    -3985
    -3986
    -3987
    -3988
    -3989
    -3990
    -3991
    -3992
    -3993
    -3994
    -3995
    -3996
    -3997
    -3998
    -3999
    -4000
    -4001
    -4002
    -4003
    -4004
    -4005
    -4006
    -4007
    -4008
    -4009
    -4010
    -4011
    -4012
    -4013
    -4014
    -4015
    -4016
    -4017
    -4018
    -4019
    -4020
    -4021
    -4022
    -4023
    -4024
    -4025
    -4026
    -4027
    -4028
    -4029
    -4030
    -4031
    -4032
    -4033
    -4034
    -4035
    -4036
    -4037
    -4038
    -4039
    -4040
    -4041
    -4042
    -4043
    -4044
    -4045
    -4046
    -4047
    -4048
    -4049
    -4050
    -4051
    -4052
    -4053
    -4054
    -4055
    -4056
    -4057
    -4058
    -4059
    -4060
    -4061
    -4062
    -4063
    -4064
    -4065
    -4066
    -4067
    -4068
    -4069
    -4070
    -4071
    -4072
    -4073
    -4074
    -4075
    -4076
    -4077
    -4078
    -4079
    -4080
    -4081
    -4082
    -4083
    -4084
    -4085
    -4086
    -4087
    -4088
    -4089
    -4090
    -4091
    -4092
    -4093
    -4094
    -4095
    -4096
    -4097
    -4098
    -4099
    -4100
    -4101
    -4102
    -4103
    -4104
    -4105
    -4106
    -4107
    -4108
    -4109
    -4110
    -4111
    -4112
    -4113
    -4114
    -4115
    -4116
    -4117
    -4118
    -4119
    -4120
    -4121
    -4122
    -4123
    -4124
    -4125
    -4126
    -4127
    -4128
    -4129
    -4130
    -4131
    -4132
    -4133
    -4134
    -4135
    -4136
    -4137
    -4138
    -4139
    -4140
    -4141
    -4142
    -4143
    -4144
    -4145
    -4146
    -4147
    -4148
    -4149
    -4150
    -4151
    -4152
    -4153
    -4154
    -4155
    -4156
    -4157
    -4158
    -4159
    -4160
    -4161
    -4162
    -4163
    -4164
    -4165
    -4166
    -4167
    -4168
    -4169
    -4170
    -4171
    -4172
    -4173
    -4174
    -4175
    -4176
    -4177
    -4178
    -4179
    -4180
    -4181
    -4182
    -4183
    -4184
    -4185
    -4186
    -4187
    -4188
    -4189
    -4190
    -4191
    -4192
    -4193
    -4194
    -4195
    -4196
    -4197
    -4198
    -4199
    -4200
    -4201
    -4202
    -4203
    -4204
    -4205
    -4206
    -4207
    -4208
    -4209
    -4210
    -4211
    -4212
    -4213
    -4214
    -4215
    -4216
    -4217
    -4218
    -4219
    -4220
    -4221
    -4222
    -4223
    -4224
    -4225
    -4226
    -4227
    -4228
    -4229
    -4230
    -4231
    -4232
    -4233
    -4234
    -4235
    -4236
    -4237
    -4238
    -4239
    -4240
    -4241
    -4242
    -4243
    -4244
    -4245
    -4246
    -4247
    -4248
    -4249
    -4250
    -4251
    -4252
    -4253
    -4254
    -4255
    -4256
    -4257
    -4258
    -4259
    -4260
    -4261
    -4262
    -4263
    -4264
    -4265
    -4266
    -4267
    -4268
    -4269
    -4270
    -4271
    -4272
    -4273
    -4274
    -4275
    -4276
    -4277
    -4278
    -4279
    -4280
    -4281
    -4282
    -4283
    -4284
    -4285
    -4286
    -4287
    -4288
    -4289
    -4290
    -4291
    -4292
    -4293
    -4294
    -4295
    -4296
    -4297
    -4298
    -4299
    -4300
    -4301
    -4302
    -4303
    -4304
    -4305
    -4306
    -4307
    -4308
    -4309
    -4310
    -4311
    -4312
    -4313
    -4314
    -4315
    -4316
    -4317
    -4318
    -4319
    -4320
    -4321
    -4322
    -4323
    -4324
    -4325
    -4326
    -4327
    -4328
    -4329
    -4330
    -4331
    -4332
    -4333
    -4334
    -4335
    -4336
    -4337
    -4338
    -4339
    -4340
    -4341
    -4342
    -4343
    -4344
    -4345
    -4346
    -4347
    -4348
    -4349
    -4350
    -4351
    -4352
    -4353
    -4354
    -4355
    -4356
    -4357
    -4358
    -4359
    -4360
    -4361
    -4362
    -4363
    -4364
    -4365
    -4366
    -4367
    -4368
    -4369
    -4370
    -4371
    -4372
    -4373
    -4374
    -4375
    -4376
    -4377
    -4378
    -4379
    -4380
    -4381
    -4382
    -4383
    -4384
    -4385
    -4386
    -4387
    -4388
    -4389
    -4390
    -4391
    -4392
    -4393
    -4394
    -4395
    -4396
    -4397
    -4398
    -4399
    -4400
    -4401
    -4402
    -4403
    -4404
    -4405
    -4406
    -4407
    -4408
    -4409
    -4410
    -4411
    -4412
    -4413
    -4414
    -4415
    -4416
    -4417
    -4418
    -4419
    -4420
    -4421
    -4422
    -4423
    -4424
    -4425
    -4426
    -4427
    -4428
    -4429
    -4430
    -4431
    -4432
    -4433
    -4434
    -4435
    -4436
    -4437
    -4438
    -4439
    -4440
    -4441
    -4442
    -4443
    -4444
    -4445
    -4446
    -4447
    -4448
    -4449
    -4450
    -4451
    -4452
    -4453
    -4454
    -4455
    -4456
    -4457
    -4458
    -4459
    -4460
    -4461
    -4462
    -4463
    -4464
    -4465
    -4466
    -4467
    -4468
    -4469
    -4470
    -4471
    -4472
    -4473
    -4474
    -4475
    -4476
    -4477
    -4478
    -4479
    -4480
    -4481
    -4482
    -4483
    -4484
    -4485
    -4486
    -4487
    -4488
    -4489
    -4490
    -4491
    -4492
    -4493
    -4494
    -4495
    -4496
    -4497
    -4498
    -4499
    -4500
    -4501
    -4502
    -4503
    -4504
    -4505
    -4506
    -4507
    -4508
    -4509
    -4510
    -4511
    -4512
    -4513
    -4514
    -4515
    -4516
    -4517
    -4518
    -4519
    -4520
    -4521
    -4522
    -4523
    -4524
    -4525
    -4526
    -4527
    -4528
    -4529
    -4530
    -4531
    -4532
    -4533
    -4534
    -4535
    -4536
    -4537
    -4538
    -4539
    -4540
    -4541
    -4542
    -4543
    -4544
    -4545
    -4546
    -4547
    -4548
    -4549
    -4550
    -4551
    -4552
    -4553
    -4554
    -4555
    -4556
    -4557
    -4558
    -4559
    -4560
    -4561
    -4562
    -4563
    -4564
    -4565
    -4566
    -4567
    -4568
    -4569
    -4570
    -4571
    -4572
    -4573
    -4574
    -4575
    -4576
    -4577
    -4578
    -4579
    -4580
    -4581
    -4582
    -4583
    -4584
    -4585
    -4586
    -4587
    -4588
    -4589
    -4590
    -4591
    -4592
    -4593
    -4594
    -4595
    -4596
    -4597
    -4598
    -4599
    -4600
    -4601
    -4602
    -4603
    -4604
    -4605
    -4606
    -4607
    -4608
    -4609
    -4610
    -4611
    -4612
    -4613
    -4614
    -4615
    -4616
    -4617
    -4618
    -4619
    -4620
    -4621
    -4622
    -4623
    -4624
    -4625
    -4626
    -4627
    -4628
    -4629
    -4630
    -4631
    -4632
    -4633
    -4634
    -4635
    -4636
    -4637
    -4638
    -4639
    -4640
    -4641
    -4642
    -4643
    -4644
    -4645
    -4646
    -4647
    -4648
    -4649
    -4650
    -4651
    -4652
    -4653
    -4654
    -4655
    -4656
    -4657
    -4658
    -4659
    -4660
    -4661
    -4662
    -4663
    -4664
    -4665
    -4666
    -4667
    -4668
    -4669
    -4670
    -4671
    -4672
    -4673
    -4674
    -4675
    -4676
    -4677
    -4678
    -4679
    -4680
    -4681
    -4682
    -4683
    -4684
    -4685
    -4686
    -4687
    -4688
    -4689
    -4690
    -4691
    -4692
    -4693
    -4694
    -4695
    -4696
    -4697
    -4698
    -4699
    -4700
    -4701
    -4702
    -4703
    -4704
    -4705
    -4706
    -4707
    -4708
    -4709
    -4710
    -4711
    -4712
    -4713
    -4714
    -4715
    -4716
    -4717
    -4718
    -4719
    -4720
    -4721
    -4722
    -4723
    -4724
    -4725
    -4726
    -4727
    -4728
    -4729
    -4730
    -4731
    -4732
    -4733
    -4734
    -4735
    -4736
    -4737
    -4738
    -4739
    -4740
    -4741
    -4742
    -4743
    -4744
    -4745
    -4746
    -4747
    -4748
    -4749
    -4750
    -4751
    -4752
    -4753
    -4754
    -4755
    -4756
    -4757
    -4758
    -4759
    -4760
    -4761
    -4762
    -4763
    -4764
    -4765
    -4766
    -4767
    -4768
    -4769
    -4770
    -4771
    -4772
    -4773
    -4774
    -4775
    -4776
    -4777
    -4778
    -4779
    -4780
    -4781
    -4782
    -4783
    -4784
    -4785
    -4786
    -4787
    -4788
    -4789
    -4790
    -4791
    -4792
    -4793
    -4794
    -4795
    -4796
    -4797
    -4798
    -4799
    -4800
    -4801
    -4802
    -4803
    -4804
    -4805
    -4806
    -4807
    -4808
    -4809
    -4810
    -4811
    -4812
    -4813
    -4814
    -4815
    -4816
    -4817
    -4818
    -4819
    -4820
    -4821
    -4822
    -4823
    -4824
    -4825
    -4826
    -4827
    -4828
    -4829
    -4830
    -4831
    -4832
    -4833
    -4834
    -4835
    -4836
    -4837
    -4838
    -4839
    -4840
    -4841
    -4842
    -4843
    -4844
    -4845
    -4846
    -4847
    -4848
    -4849
    -4850
    -4851
    -4852
    -4853
    -4854
    -4855
    -4856
    -4857
    -4858
    -4859
    -4860
    -4861
    -4862
    -4863
    -4864
    -4865
    -4866
    -4867
    -4868
    -4869
    -4870
    -4871
    -4872
    -4873
    -4874
    -4875
    -4876
    -4877
    -4878
    -4879
    -4880
    -4881
    -4882
    -4883
    -4884
    -4885
    -4886
    -4887
    -4888
    -4889
    -4890
    -4891
    -4892
    -4893
    -4894
    -4895
    -4896
    -4897
    -4898
    -4899
    -4900
    -4901
    -4902
    -4903
    -4904
    -4905
    -4906
    -4907
    -4908
    -4909
    -4910
    -4911
    -4912
    -4913
    -4914
    -4915
    -4916
    -4917
    -4918
    -4919
    -4920
    -4921
    -4922
    -4923
    -4924
    -4925
    -4926
    -4927
    -4928
    -4929
    -4930
    -4931
    -4932
    -4933
    -4934
    -4935
    -4936
    -4937
    -4938
    -4939
    -4940
    -4941
    -4942
    -4943
    -4944
    -4945
    -4946
    -4947
    -4948
    -4949
    -4950
    -4951
    -4952
    -4953
    -4954
    -4955
    -4956
    -4957
    -4958
    -4959
    -4960
    -4961
    -4962
    -4963
    -4964
    -4965
    -4966
    -4967
    -4968
    -4969
    -4970
    -4971
    -4972
    -4973
    -4974
    -4975
    -4976
    -4977
    -4978
    -4979
    -4980
    -4981
    -4982
    -4983
    -4984
    -4985
    -4986
    -4987
    -4988
    -4989
    -4990
    -4991
    -4992
    -4993
    -4994
    -4995
    -4996
    -4997
    -4998
    -4999
    -5000
    -5001
    -5002
    -5003
    -5004
    -5005
    -5006
    -5007
    -5008
    -5009
    -5010
    -5011
    -5012
    -5013
    -5014
    -5015
    -5016
    -5017
    -5018
    -5019
    -5020
    -5021
    -5022
    -5023
    -5024
    -5025
    -5026
    -5027
    -5028
    -5029
    -5030
    -5031
    -5032
    -5033
    -5034
    -5035
    -5036
    -5037
    -5038
    -5039
    -5040
    -5041
    -5042
    -5043
    -5044
    -5045
    -5046
    -5047
    -5048
    -5049
    -5050
    -5051
    -5052
    -5053
    -5054
    -5055
    -5056
    -5057
    -5058
    -5059
    -5060
    -5061
    -5062
    -5063
    -5064
    -5065
    -5066
    -5067
    -5068
    -5069
    -5070
    -5071
    -5072
    -5073
    -5074
    -5075
    -5076
    -5077
    -5078
    -5079
    -5080
    -5081
    -5082
    -5083
    -5084
    -5085
    -5086
    -5087
    -5088
    -5089
    -5090
    -5091
    -5092
    -5093
    -5094
    -5095
    -5096
    -5097
    -5098
    -5099
    -5100
    -5101
    -5102
    -5103
    -5104
    -5105
    -5106
    -5107
    -5108
    -5109
    -5110
    -5111
    -5112
    -5113
    -5114
    -5115
    -5116
    -5117
    -5118
    -5119
    -5120
    -5121
    -5122
    -5123
    -5124
    -5125
    -5126
    -5127
    -5128
    -5129
    -5130
    -5131
    -5132
    -5133
    -5134
    -5135
    -5136
    -5137
    -5138
    -5139
    -5140
    -5141
    -5142
    -5143
    -5144
    -5145
    -5146
    -5147
    -5148
    -5149
    -5150
    -5151
    -5152
    -5153
    -5154
    -5155
    -5156
    -5157
    -5158
    -5159
    -5160
    -5161
    -5162
    -5163
    -5164
    -5165
    -5166
    -5167
    -5168
    -5169
    -5170
    -5171
    -5172
    -5173
    -5174
    -5175
    -5176
    -5177
    -5178
    -5179
    -5180
    -5181
    -5182
    -5183
    -5184
    -5185
    -5186
    -5187
    -5188
    -5189
    -5190
    -5191
    -5192
    -5193
    -5194
    -5195
    -5196
    -5197
    -5198
    -5199
    -5200
    -5201
    -5202
    -5203
    -5204
    -5205
    -5206
    -5207
    -5208
    -5209
    -5210
    -5211
    -5212
    -5213
    -5214
    -5215
    -5216
    -5217
    -5218
    -5219
    -5220
    -5221
    -5222
    -5223
    -5224
    -5225
    -5226
    -5227
    -5228
    -5229
    -5230
    -5231
    -5232
    -5233
    -5234
    -5235
    -5236
    -5237
    -5238
    -5239
    -5240
    -5241
    -5242
    -5243
    -5244
    -5245
    -5246
    -5247
    -5248
    -5249
    -5250
    -5251
    -5252
    -5253
    -5254
    -5255
    -5256
    -5257
    -5258
    -5259
    -5260
    -5261
    -5262
    -5263
    -5264
    -5265
    -5266
    -5267
    -5268
    -5269
    -5270
    -5271
    -5272
    -5273
    -5274
    -5275
    -5276
    -5277
    -5278
    -5279
    -5280
    -5281
    -5282
    -5283
    -5284
    -5285
    -5286
    -5287
    -5288
    -5289
    -5290
    -5291
    -5292
    -5293
    -5294
    -5295
    -5296
    -5297
    -5298
    -5299
    -5300
    -5301
    -5302
    -5303
    -5304
    -5305
    -5306
    -5307
    -5308
    -5309
    -5310
    -5311
    -5312
    -5313
    -5314
    -5315
    -5316
    -5317
    -5318
    -5319
    -5320
    -5321
    -5322
    -5323
    -5324
    -5325
    -5326
    -5327
    -5328
    -5329
    -5330
    -5331
    -5332
    -5333
    -5334
    -5335
    -5336
    -5337
    -5338
    -5339
    -5340
    -5341
    -5342
    -5343
    -5344
    -5345
    -5346
    -5347
    -5348
    -5349
    -5350
    -5351
    -5352
    -5353
    -5354
    -5355
    -5356
    -5357
    -5358
    -5359
    -5360
    -5361
    -5362
    -5363
    -5364
    -5365
    -5366
    -5367
    -5368
    -5369
    -5370
    -5371
    -5372
    -5373
    -5374
    -5375
    -5376
    -5377
    -5378
    -5379
    -5380
    -5381
    -5382
    -5383
    -5384
    -5385
    -5386
    -5387
    -5388
    -5389
    -5390
    -5391
    -5392
    -5393
    -5394
    -5395
    -5396
    -5397
    -5398
    -5399
    -5400
    -5401
    -5402
    -5403
    -5404
    -5405
    -5406
    -5407
    -5408
    -5409
    -5410
    -5411
    -5412
    -5413
    -5414
    -5415
    -5416
    -5417
    -5418
    -5419
    -5420
    -5421
    -5422
    -5423
    -5424
    -5425
    -5426
    -5427
    -5428
    -5429
    -5430
    -5431
    -5432
    -5433
    -5434
    -5435
    -5436
    -5437
    -5438
    -5439
    -5440
    -5441
    -5442
    -5443
    -5444
    -5445
    -5446
    -5447
    -5448
    -5449
    -5450
    -5451
    -5452
    -5453
    -5454
    -5455
    -5456
    -5457
    -5458
    -5459
    -5460
    -5461
    -5462
    -5463
    -5464
    -5465
    -5466
    -5467
    -5468
    -5469
    -5470
    -5471
    -5472
    -5473
    -5474
    -5475
    -5476
    -5477
    -5478
    -5479
    -5480
    -5481
    -5482
    -5483
    -5484
    -5485
    -5486
    -5487
    -5488
    -5489
    -5490
    -5491
    -5492
    -5493
    -5494
    -5495
    -5496
    -5497
    -5498
    -5499
    -5500
    -5501
    -5502
    -5503
    -5504
    -5505
    -5506
    -5507
    -5508
    -5509
    -5510
    -5511
    -5512
    -5513
    -5514
    -5515
    -5516
    -5517
    -5518
    -5519
    -5520
    -5521
    -5522
    -5523
    -5524
    -5525
    -5526
    -5527
    -5528
    -5529
    -5530
    -5531
    -5532
    -5533
    -5534
    -5535
    -5536
    -5537
    -5538
    -5539
    -5540
    -5541
    -5542
    -5543
    -5544
    -5545
    -5546
    -5547
    -5548
    -5549
    -5550
    -5551
    -5552
    -5553
    -5554
    -5555
    -5556
    -5557
    -5558
    -5559
    -5560
    -5561
    -5562
    -5563
    -5564
    -5565
    -5566
    -5567
    -5568
    -5569
    -5570
    -5571
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -5584,24 +1815,28 @@
     //! Wallet
     //!
     //! This module defines the [`Wallet`] structure.
    -
    -use std::cell::RefCell;
    -use std::collections::HashMap;
    -use std::collections::{BTreeMap, HashSet};
    -use std::fmt;
    -use std::ops::Deref;
    -use std::str::FromStr;
    -use std::sync::Arc;
    -
    -use bitcoin::secp256k1::Secp256k1;
    -
    +use crate::collections::{BTreeMap, HashMap, HashSet};
    +use alloc::{
    +    boxed::Box,
    +    string::{String, ToString},
    +    sync::Arc,
    +    vec::Vec,
    +};
    +pub use bdk_chain::keychain::Balance;
    +use bdk_chain::{
    +    chain_graph,
    +    keychain::{persist, KeychainChangeSet, KeychainScan, KeychainTracker},
    +    sparse_chain, BlockId, ConfirmationTime,
    +};
     use bitcoin::consensus::encode::serialize;
    +use bitcoin::secp256k1::Secp256k1;
     use bitcoin::util::psbt;
     use bitcoin::{
    -    Address, EcdsaSighashType, LockTime, Network, OutPoint, SchnorrSighashType, Script, Sequence,
    -    Transaction, TxOut, Txid, Witness,
    +    Address, BlockHash, EcdsaSighashType, LockTime, Network, OutPoint, SchnorrSighashType, Script,
    +    Sequence, Transaction, TxOut, Txid, Witness,
     };
    -
    +use core::fmt;
    +use core::ops::Deref;
     use miniscript::psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier};
     
     #[allow(unused_imports)]
    @@ -5610,12 +1845,8 @@
     pub mod coin_selection;
     pub mod export;
     pub mod signer;
    -pub mod time;
     pub mod tx_builder;
     pub(crate) mod utils;
    -#[cfg(feature = "verify")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
    -pub mod verify;
     
     #[cfg(feature = "hardware-signer")]
     #[cfg_attr(docsrs, doc(cfg(feature = "hardware-signer")))]
    @@ -5623,15 +1854,12 @@
     
     pub use utils::IsDust;
     
    -use coin_selection::DefaultCoinSelectionAlgorithm;
    +#[allow(deprecated)]
    +use coin_selection::DefaultCoinSelectionAlgorithm;
     use signer::{SignOptions, SignerOrdering, SignersContainer, TransactionSigner};
     use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxParams};
     use utils::{check_nsequence_rbf, After, Older, SecpCtx};
     
    -use crate::blockchain::{GetHeight, NoopProgress, Progress, WalletSync};
    -use crate::database::memory::MemoryDatabase;
    -use crate::database::{AnyDatabase, BatchDatabase, BatchOperations, DatabaseUtils, SyncTime};
    -use crate::descriptor::checksum::calc_checksum_bytes_internal;
     use crate::descriptor::policy::BuildSatisfaction;
     use crate::descriptor::{
         calc_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DescriptorMeta,
    @@ -5640,11 +1868,9 @@
     use crate::error::{Error, MiniscriptPsbtError};
     use crate::psbt::PsbtUtils;
     use crate::signer::SignerError;
    -use crate::testutils;
     use crate::types::*;
     use crate::wallet::coin_selection::Excess::{Change, NoChange};
     
    -const CACHE_ADDR_BATCH_SIZE: u32 = 100;
     const COINBASE_MATURITY: u32 = 100;
     
     /// A Bitcoin wallet
    @@ -5653,26 +1879,27 @@
     /// Its main components are:
     ///
     /// 1. output *descriptors* from which it can derive addresses.
    -/// 2. A [`Database`] where it tracks transactions and utxos related to the descriptors.
    -/// 3. [`signer`]s that can contribute signatures to addresses instantiated from the descriptors.
    +/// 2. [`signer`]s that can contribute signatures to addresses instantiated from the descriptors.
     ///
    -/// [`Database`]: crate::database::Database
     /// [`signer`]: crate::signer
     #[derive(Debug)]
    -pub struct Wallet<D> {
    -    descriptor: ExtendedDescriptor,
    -    change_descriptor: Option<ExtendedDescriptor>,
    -
    +pub struct Wallet<D = ()> {
         signers: Arc<SignersContainer>,
         change_signers: Arc<SignersContainer>,
    -
    +    keychain_tracker: KeychainTracker<KeychainKind, ConfirmationTime>,
    +    persist: persist::Persist<KeychainKind, ConfirmationTime, D>,
         network: Network,
    -
    -    database: RefCell<D>,
    -
         secp: SecpCtx,
     }
     
    +/// The update to a [`Wallet`] used in [`Wallet::apply_update`]. This is usually returned from blockchain data sources.
    +/// The type parameter `T` indicates the kind of transaction contained in the update. It's usually a [`bitcoin::Transaction`].
    +pub type Update = KeychainScan<KeychainKind, ConfirmationTime>;
    +/// Error indicating that something was wrong with an [`Update<T>`].
    +pub type UpdateError = chain_graph::UpdateError<ConfirmationTime>;
    +/// The changeset produced internally by applying an update
    +pub(crate) type ChangeSet = KeychainChangeSet<KeychainKind, ConfirmationTime>;
    +
     /// The address index selection strategy to use to derived an address from the wallet's external
     /// descriptor. See [`Wallet::get_address`]. If you're unsure which one to use use `WalletIndex::New`.
     #[derive(Debug)]
    @@ -5693,15 +1920,6 @@
         /// Use with caution, if an index is given that is less than the current descriptor index
         /// then the returned address may have already been used.
         Peek(u32),
    -    /// Return the address for a specific descriptor index and reset the current descriptor index
    -    /// used by `AddressIndex::New` and `AddressIndex::LastUsed` to this value.
    -    ///
    -    /// Use with caution, if an index is given that is less than the current descriptor index
    -    /// then the returned address and subsequent addresses returned by calls to `AddressIndex::New`
    -    /// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a
    -    /// value earlier than the [`crate::blockchain::Blockchain`] stop_gap (default is 20) then a
    -    /// larger stop_gap should be used to monitor for all possibly used addresses.
    -    Reset(u32),
     }
     
     /// A derived address and the index it was found at.
    @@ -5730,57 +1948,72 @@
         }
     }
     
    -#[derive(Debug, Default)]
    -/// Options to a [`sync`].
    -///
    -/// [`sync`]: Wallet::sync
    -pub struct SyncOptions {
    -    /// The progress tracker which may be informed when progress is made.
    -    pub progress: Option<Box<dyn Progress>>,
    +impl Wallet {
    +    /// Creates a wallet that does not persist data.
    +    pub fn new_no_persist<E: IntoWalletDescriptor>(
    +        descriptor: E,
    +        change_descriptor: Option<E>,
    +        network: Network,
    +    ) -> Result<Self, crate::descriptor::DescriptorError> {
    +        Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e {
    +            NewError::Descriptor(e) => e,
    +            NewError::Persist(_) => unreachable!("no persistence so it can't fail"),
    +        })
    +    }
    +}
    +
    +#[derive(Debug)]
    +/// Error returned from [`Wallet::new`]
    +pub enum NewError<P> {
    +    /// There was problem with the descriptors passed in
    +    Descriptor(crate::descriptor::DescriptorError),
    +    /// We were unable to load the wallet's data from the persistance backend
    +    Persist(P),
     }
     
    -impl<D> Wallet<D>
    +impl<P> core::fmt::Display for NewError<P>
     where
    -    D: BatchDatabase,
    +    P: core::fmt::Display,
     {
    -    #[deprecated = "Just use Wallet::new -- all wallets are offline now!"]
    -    /// Create a new "offline" wallet
    -    pub fn new_offline<E: IntoWalletDescriptor>(
    -        descriptor: E,
    -        change_descriptor: Option<E>,
    -        network: Network,
    -        database: D,
    -    ) -> Result<Self, Error> {
    -        Self::new(descriptor, change_descriptor, network, database)
    +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    +        match self {
    +            NewError::Descriptor(e) => e.fmt(f),
    +            NewError::Persist(e) => {
    +                write!(f, "failed to load wallet from persistance backend: {}", e)
    +            }
    +        }
         }
    +}
     
    -    /// Create a wallet.
    -    ///
    -    /// The only way this can fail is if the descriptors passed in do not match the checksums in `database`.
    +#[cfg(feature = "std")]
    +impl<P: core::fmt::Display + core::fmt::Debug> std::error::Error for NewError<P> {}
    +
    +impl<D> Wallet<D> {
    +    /// Create a wallet from a `descriptor` (and an optional `change_descriptor`) and load related
    +    /// transaction data from `db`.
         pub fn new<E: IntoWalletDescriptor>(
             descriptor: E,
             change_descriptor: Option<E>,
    +        mut db: D,
             network: Network,
    -        mut database: D,
    -    ) -> Result<Self, Error> {
    +    ) -> Result<Self, NewError<D::LoadError>>
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
             let secp = Secp256k1::new();
     
    -        let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, &secp, network)?;
    -        Self::db_checksum(
    -            &mut database,
    -            &descriptor.to_string(),
    -            KeychainKind::External,
    -        )?;
    +        let mut keychain_tracker = KeychainTracker::default();
    +        let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, &secp, network)
    +            .map_err(NewError::Descriptor)?;
    +        keychain_tracker
    +            .txout_index
    +            .add_keychain(KeychainKind::External, descriptor.clone());
             let signers = Arc::new(SignersContainer::build(keymap, &descriptor, &secp));
    -        let (change_descriptor, change_signers) = match change_descriptor {
    +        let change_signers = match change_descriptor {
                 Some(desc) => {
                     let (change_descriptor, change_keymap) =
    -                    into_wallet_descriptor_checked(desc, &secp, network)?;
    -                Self::db_checksum(
    -                    &mut database,
    -                    &change_descriptor.to_string(),
    -                    KeychainKind::Internal,
    -                )?;
    +                    into_wallet_descriptor_checked(desc, &secp, network)
    +                        .map_err(NewError::Descriptor)?;
     
                     let change_signers = Arc::new(SignersContainer::build(
                         change_keymap,
    @@ -5788,123 +2021,47 @@
                         &secp,
                     ));
     
    -                (Some(change_descriptor), change_signers)
    +                keychain_tracker
    +                    .txout_index
    +                    .add_keychain(KeychainKind::Internal, change_descriptor);
    +
    +                change_signers
                 }
    -            None => (None, Arc::new(SignersContainer::new())),
    +            None => Arc::new(SignersContainer::new()),
             };
     
    +        db.load_into_keychain_tracker(&mut keychain_tracker)
    +            .map_err(NewError::Persist)?;
    +
    +        let persist = persist::Persist::new(db);
    +
             Ok(Wallet {
    -            descriptor,
    -            change_descriptor,
                 signers,
                 change_signers,
                 network,
    -            database: RefCell::new(database),
    +            persist,
                 secp,
    +            keychain_tracker,
             })
         }
     
    -    /// This checks the checksum within [`BatchDatabase`] twice (if needed). The first time with the
    -    /// actual checksum, and the second time with the checksum of `descriptor+checksum`. The second
    -    /// check is necessary for backwards compatibility of a checksum-inception bug.
    -    fn db_checksum(db: &mut D, desc: &str, kind: KeychainKind) -> Result<(), Error> {
    -        let checksum = calc_checksum_bytes_internal(desc, true)?;
    -        if db.check_descriptor_checksum(kind, checksum).is_ok() {
    -            return Ok(());
    -        }
    -
    -        let checksum_inception = calc_checksum_bytes_internal(desc, false)?;
    -        db.check_descriptor_checksum(kind, checksum_inception)
    -    }
    -
         /// Get the Bitcoin network the wallet is using.
         pub fn network(&self) -> Network {
             self.network
         }
     
    -    // Return a newly derived address for the specified `keychain`.
    -    fn get_new_address(&self, keychain: KeychainKind) -> Result<AddressInfo, Error> {
    -        let incremented_index = self.fetch_and_increment_index(keychain)?;
    -
    -        let address_result = self
    -            .get_descriptor_for_keychain(keychain)
    -            .at_derivation_index(incremented_index)
    -            .address(self.network);
    -
    -        address_result
    -            .map(|address| AddressInfo {
    -                address,
    -                index: incremented_index,
    -                keychain,
    -            })
    -            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    -    }
    -
    -    // Return the the last previously derived address for `keychain` if it has not been used in a
    -    // received transaction. Otherwise return a new address using [`Wallet::get_new_address`].
    -    fn get_unused_address(&self, keychain: KeychainKind) -> Result<AddressInfo, Error> {
    -        let current_index = self.fetch_index(keychain)?;
    -
    -        let derived_key = self
    -            .get_descriptor_for_keychain(keychain)
    -            .at_derivation_index(current_index);
    -
    -        let script_pubkey = derived_key.script_pubkey();
    -
    -        let found_used = self
    -            .list_transactions(true)?
    -            .iter()
    -            .flat_map(|tx_details| tx_details.transaction.as_ref())
    -            .flat_map(|tx| tx.output.iter())
    -            .any(|o| o.script_pubkey == script_pubkey);
    -
    -        if found_used {
    -            self.get_new_address(keychain)
    -        } else {
    -            derived_key
    -                .address(self.network)
    -                .map(|address| AddressInfo {
    -                    address,
    -                    index: current_index,
    -                    keychain,
    -                })
    -                .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    -        }
    -    }
    -
    -    // Return derived address for the descriptor of given [`KeychainKind`] at a specific index
    -    fn peek_address(&self, index: u32, keychain: KeychainKind) -> Result<AddressInfo, Error> {
    -        self.get_descriptor_for_keychain(keychain)
    -            .at_derivation_index(index)
    -            .address(self.network)
    -            .map(|address| AddressInfo {
    -                index,
    -                address,
    -                keychain,
    -            })
    -            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    -    }
    -
    -    // Return derived address for `keychain` at a specific index and reset current
    -    // address index
    -    fn reset_address(&self, index: u32, keychain: KeychainKind) -> Result<AddressInfo, Error> {
    -        self.set_index(keychain, index)?;
    -
    -        self.get_descriptor_for_keychain(keychain)
    -            .at_derivation_index(index)
    -            .address(self.network)
    -            .map(|address| AddressInfo {
    -                index,
    -                address,
    -                keychain,
    -            })
    -            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    +    /// Iterator over all keychains in this wallet
    +    pub fn keychanins(&self) -> &BTreeMap<KeychainKind, ExtendedDescriptor> {
    +        self.keychain_tracker.txout_index.keychains()
         }
     
         /// Return a derived address using the external descriptor, see [`AddressIndex`] for
         /// available address index selection strategies. If none of the keys in the descriptor are derivable
         /// (i.e. does not end with /*) then the same address will always be returned for any [`AddressIndex`].
    -    pub fn get_address(&self, address_index: AddressIndex) -> Result<AddressInfo, Error> {
    +    pub fn get_address(&mut self, address_index: AddressIndex) -> AddressInfo
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
             self._get_address(address_index, KeychainKind::External)
         }
     
    @@ -5915,174 +2072,268 @@
         /// see [`AddressIndex`] for available address index selection strategies. If none of the keys
         /// in the descriptor are derivable (i.e. does not end with /*) then the same address will always
         /// be returned for any [`AddressIndex`].
    -    pub fn get_internal_address(&self, address_index: AddressIndex) -> Result<AddressInfo, Error> {
    +    pub fn get_internal_address(&mut self, address_index: AddressIndex) -> AddressInfo
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
             self._get_address(address_index, KeychainKind::Internal)
         }
     
    -    fn _get_address(
    -        &self,
    -        address_index: AddressIndex,
    -        keychain: KeychainKind,
    -    ) -> Result<AddressInfo, Error> {
    -        match address_index {
    -            AddressIndex::New => self.get_new_address(keychain),
    -            AddressIndex::LastUnused => self.get_unused_address(keychain),
    -            AddressIndex::Peek(index) => self.peek_address(index, keychain),
    -            AddressIndex::Reset(index) => self.reset_address(index, keychain),
    +    fn _get_address(&mut self, address_index: AddressIndex, keychain: KeychainKind) -> AddressInfo
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
    +        let keychain = self.map_keychain(keychain);
    +        let txout_index = &mut self.keychain_tracker.txout_index;
    +        let (index, spk) = match address_index {
    +            AddressIndex::New => {
    +                let ((index, spk), changeset) = txout_index.reveal_next_spk(&keychain);
    +                let spk = spk.clone();
    +
    +                self.persist.stage(changeset.into());
    +                self.persist.commit().expect("TODO");
    +                (index, spk)
    +            }
    +            AddressIndex::LastUnused => {
    +                let index = txout_index.last_revealed_index(&keychain);
    +                match index {
    +                    Some(index) if !txout_index.is_used(&(keychain, index)) => (
    +                        index,
    +                        txout_index
    +                            .spk_at_index(&(keychain, index))
    +                            .expect("must exist")
    +                            .clone(),
    +                    ),
    +                    _ => return self._get_address(AddressIndex::New, keychain),
    +                }
    +            }
    +            AddressIndex::Peek(index) => txout_index
    +                .spks_of_keychain(&keychain)
    +                .take(index as usize + 1)
    +                .last()
    +                .unwrap(),
    +        };
    +        AddressInfo {
    +            index,
    +            address: Address::from_script(&spk, self.network)
    +                .expect("descriptor must have address form"),
    +            keychain,
             }
         }
     
    -    /// Ensures that there are at least `max_addresses` addresses cached in the database if the
    -    /// descriptor is derivable, or 1 address if it is not.
    -    /// Will return `Ok(true)` if there are new addresses generated (either external or internal),
    -    /// and `Ok(false)` if all the required addresses are already cached. This function is useful to
    -    /// explicitly cache addresses in a wallet to do things like check [`Wallet::is_mine`] on
    -    /// transaction output scripts.
    -    pub fn ensure_addresses_cached(&self, max_addresses: u32) -> Result<bool, Error> {
    -        let mut new_addresses_cached = false;
    -        let max_address = match self.descriptor.has_wildcard() {
    -            false => 0,
    -            true => max_addresses,
    -        };
    -        debug!("max_address {}", max_address);
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(KeychainKind::External, max_address.saturating_sub(1))?
    -            .is_none()
    -        {
    -            debug!("caching external addresses");
    -            new_addresses_cached = true;
    -            self.cache_addresses(KeychainKind::External, 0, max_address)?;
    -        }
    +    /// Return whether or not a `script` is part of this wallet (either internal or external)
    +    pub fn is_mine(&self, script: &Script) -> bool {
    +        self.keychain_tracker
    +            .txout_index
    +            .index_of_spk(script)
    +            .is_some()
    +    }
     
    -        if let Some(change_descriptor) = &self.change_descriptor {
    -            let max_address = match change_descriptor.has_wildcard() {
    -                false => 0,
    -                true => max_addresses,
    -            };
    +    /// Finds how the wallet derived the script pubkey `spk`.
    +    ///
    +    /// Will only return `Some(_)` if the wallet has given out the spk.
    +    pub fn derivation_of_spk(&self, spk: &Script) -> Option<(KeychainKind, u32)> {
    +        self.keychain_tracker.txout_index.index_of_spk(spk).copied()
    +    }
     
    -            if self
    -                .database
    -                .borrow()
    -                .get_script_pubkey_from_path(KeychainKind::Internal, max_address.saturating_sub(1))?
    -                .is_none()
    -            {
    -                debug!("caching internal addresses");
    -                new_addresses_cached = true;
    -                self.cache_addresses(KeychainKind::Internal, 0, max_address)?;
    -            }
    -        }
    -        Ok(new_addresses_cached)
    +    /// Return the list of unspent outputs of this wallet
    +    pub fn list_unspent(&self) -> Vec<LocalUtxo> {
    +        self.keychain_tracker
    +            .full_utxos()
    +            .map(|(&(keychain, derivation_index), utxo)| LocalUtxo {
    +                outpoint: utxo.outpoint,
    +                txout: utxo.txout,
    +                keychain,
    +                is_spent: false,
    +                derivation_index,
    +                confirmation_time: utxo.chain_position,
    +            })
    +            .collect()
         }
     
    -    /// Return whether or not a `script` is part of this wallet (either internal or external)
    -    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
    -        self.database.borrow().is_mine(script)
    +    /// Get all the checkpoints the wallet is currently storing indexed by height.
    +    pub fn checkpoints(&self) -> &BTreeMap<u32, BlockHash> {
    +        self.keychain_tracker.chain().checkpoints()
         }
     
    -    /// Return the list of unspent outputs of this wallet
    +    /// Returns the latest checkpoint.
    +    pub fn latest_checkpoint(&self) -> Option<BlockId> {
    +        self.keychain_tracker.chain().latest_checkpoint()
    +    }
    +
    +    /// Returns a iterators of all the script pubkeys for the `Internal` and External` variants in `KeychainKind`.
    +    ///
    +    /// This is inteded to be used when doing a full scan of your addresses (e.g. after restoring
    +    /// from seed words). You pass the `BTreeMap` of iterators to a blockchain data source (e.g.
    +    /// electrum server) which will go through each address until it reaches a *stop grap*.
    +    ///
    +    /// Note carefully that iterators go over **all** script pubkeys on the keychains (not what
    +    /// script pubkeys the wallet is storing internally).
    +    pub fn spks_of_all_keychains(
    +        &self,
    +    ) -> BTreeMap<KeychainKind, impl Iterator<Item = (u32, Script)> + Clone> {
    +        self.keychain_tracker.txout_index.spks_of_all_keychains()
    +    }
    +
    +    /// Gets an iterator over all the script pubkeys in a single keychain.
    +    ///
    +    /// See [`spks_of_all_keychains`] for more documentation
         ///
    -    /// Note that this method only operates on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_unspent(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        Ok(self
    -            .database
    -            .borrow()
    -            .iter_utxos()?
    -            .into_iter()
    -            .filter(|l| !l.is_spent)
    -            .collect())
    +    /// [`spks_of_all_keychains`]: Self::spks_of_all_keychains
    +    pub fn spks_of_keychain(
    +        &self,
    +        keychain: KeychainKind,
    +    ) -> impl Iterator<Item = (u32, Script)> + Clone {
    +        self.keychain_tracker
    +            .txout_index
    +            .spks_of_keychain(&keychain)
         }
     
    -    /// Returns the `UTXO` owned by this wallet corresponding to `outpoint` if it exists in the
    +    /// Returns the utxo owned by this wallet corresponding to `outpoint` if it exists in the
         /// wallet's database.
    -    pub fn get_utxo(&self, outpoint: OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        self.database.borrow().get_utxo(&outpoint)
    +    pub fn get_utxo(&self, op: OutPoint) -> Option<LocalUtxo> {
    +        self.keychain_tracker
    +            .full_utxos()
    +            .find_map(|(&(keychain, derivation_index), txo)| {
    +                if op == txo.outpoint {
    +                    Some(LocalUtxo {
    +                        outpoint: txo.outpoint,
    +                        txout: txo.txout,
    +                        keychain,
    +                        is_spent: txo.spent_by.is_none(),
    +                        derivation_index,
    +                        confirmation_time: txo.chain_position,
    +                    })
    +                } else {
    +                    None
    +                }
    +            })
         }
     
         /// Return a single transactions made and received by the wallet
         ///
         /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
         /// `include_raw` is `true`.
    +    pub fn get_tx(&self, txid: Txid, include_raw: bool) -> Option<TransactionDetails> {
    +        let (&confirmation_time, tx) = self.keychain_tracker.chain_graph().get_tx_in_chain(txid)?;
    +        let graph = self.keychain_tracker.graph();
    +        let txout_index = &self.keychain_tracker.txout_index;
    +
    +        let received = tx
    +            .output
    +            .iter()
    +            .map(|txout| {
    +                if txout_index.index_of_spk(&txout.script_pubkey).is_some() {
    +                    txout.value
    +                } else {
    +                    0
    +                }
    +            })
    +            .sum();
    +
    +        let sent = tx
    +            .input
    +            .iter()
    +            .map(|txin| {
    +                if let Some((_, txout)) = txout_index.txout(txin.previous_output) {
    +                    txout.value
    +                } else {
    +                    0
    +                }
    +            })
    +            .sum();
    +
    +        let inputs = tx
    +            .input
    +            .iter()
    +            .map(|txin| {
    +                graph
    +                    .get_txout(txin.previous_output)
    +                    .map(|txout| txout.value)
    +            })
    +            .sum::<Option<u64>>();
    +        let outputs = tx.output.iter().map(|txout| txout.value).sum();
    +        let fee = inputs.map(|inputs| inputs.saturating_sub(outputs));
    +
    +        Some(TransactionDetails {
    +            transaction: if include_raw { Some(tx.clone()) } else { None },
    +            txid,
    +            received,
    +            sent,
    +            fee,
    +            confirmation_time,
    +        })
    +    }
    +
    +    /// Add a new checkpoint to the wallet's internal view of the chain.
    +    /// This stages but does not [`commit`] the change.
         ///
    -    /// Note that this method only operates on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn get_tx(
    -        &self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        self.database.borrow().get_tx(txid, include_raw)
    +    /// Returns whether anything changed with the insertion (e.g. `false` if checkpoint was already
    +    /// there).
    +    ///
    +    /// [`commit`]: Self::commit
    +    pub fn insert_checkpoint(
    +        &mut self,
    +        block_id: BlockId,
    +    ) -> Result<bool, sparse_chain::InsertCheckpointError> {
    +        let changeset = self.keychain_tracker.insert_checkpoint(block_id)?;
    +        let changed = changeset.is_empty();
    +        self.persist.stage(changeset);
    +        Ok(changed)
         }
     
    -    /// Return an unsorted list of transactions made and received by the wallet
    +    /// Add a transaction to the wallet's internal view of the chain.
    +    /// This stages but does not [`commit`] the change.
         ///
    -    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
    -    /// `include_raw` is `true`.
    +    /// There are a number reasons `tx` could be rejected with an `Err(_)`. The most important one
    +    /// is that the transaction is at a height that is greater than [`latest_checkpoint`]. Therefore
    +    /// you should use [`insert_checkpoint`] to insert new checkpoints before manually inserting new
    +    /// transactions.
         ///
    -    /// To sort transactions, the following code can be used:
    -    /// ```no_run
    -    /// # let mut tx_list: Vec<bdk::TransactionDetails> = vec![];
    -    /// tx_list.sort_by(|a, b| {
    -    ///     b.confirmation_time
    -    ///         .as_ref()
    -    ///         .map(|t| t.height)
    -    ///         .cmp(&a.confirmation_time.as_ref().map(|t| t.height))
    -    /// });
    -    /// ```
    +    /// Returns whether anything changed with the transaction insertion (e.g. `false` if the
    +    /// transaction was already inserted at the same position).
         ///
    -    /// Note that this method only operates on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        self.database.borrow().iter_txs(include_raw)
    +    /// [`commit`]: Self::commit
    +    /// [`latest_checkpoint`]: Self::latest_checkpoint
    +    /// [`insert_checkpoint`]: Self::insert_checkpoint
    +    pub fn insert_tx(
    +        &mut self,
    +        tx: Transaction,
    +        position: ConfirmationTime,
    +    ) -> Result<bool, chain_graph::InsertTxError<ConfirmationTime>> {
    +        let changeset = self.keychain_tracker.insert_tx(tx, position)?;
    +        let changed = changeset.is_empty();
    +        self.persist.stage(changeset);
    +        Ok(changed)
    +    }
    +
    +    #[deprecated(note = "use Wallet::transactions instead")]
    +    /// Deprecated. use `Wallet::transactions` instead.
    +    pub fn list_transactions(&self, include_raw: bool) -> Vec<TransactionDetails> {
    +        self.keychain_tracker
    +            .chain()
    +            .txids()
    +            .map(|&(_, txid)| self.get_tx(txid, include_raw).expect("must exist"))
    +            .collect()
    +    }
    +
    +    /// Iterate over the transactions in the wallet in order of ascending confirmation time with
    +    /// unconfirmed transactions last.
    +    pub fn transactions(
    +        &self,
    +    ) -> impl DoubleEndedIterator<Item = (ConfirmationTime, &Transaction)> + '_ {
    +        self.keychain_tracker
    +            .chain_graph()
    +            .transactions_in_chain()
    +            .map(|(pos, tx)| (*pos, tx))
         }
     
         /// Return the balance, separated into available, trusted-pending, untrusted-pending and immature
         /// values.
    -    ///
    -    /// Note that this method only operates on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn get_balance(&self) -> Result<Balance, Error> {
    -        let mut immature = 0;
    -        let mut trusted_pending = 0;
    -        let mut untrusted_pending = 0;
    -        let mut confirmed = 0;
    -        let utxos = self.list_unspent()?;
    -        let database = self.database.borrow();
    -        let last_sync_height = match database
    -            .get_sync_time()?
    -            .map(|sync_time| sync_time.block_time.height)
    -        {
    -            Some(height) => height,
    -            // None means database was never synced
    -            None => return Ok(Balance::default()),
    -        };
    -        for u in utxos {
    -            // Unwrap used since utxo set is created from database
    -            let tx = database
    -                .get_tx(&u.outpoint.txid, true)?
    -                .expect("Transaction not found in database");
    -            if let Some(tx_conf_time) = &tx.confirmation_time {
    -                if tx.transaction.expect("No transaction").is_coin_base()
    -                    && (last_sync_height - tx_conf_time.height) < COINBASE_MATURITY
    -                {
    -                    immature += u.txout.value;
    -                } else {
    -                    confirmed += u.txout.value;
    -                }
    -            } else if u.keychain == KeychainKind::Internal {
    -                trusted_pending += u.txout.value;
    -            } else {
    -                untrusted_pending += u.txout.value;
    -            }
    -        }
    -
    -        Ok(Balance {
    -            immature,
    -            trusted_pending,
    -            untrusted_pending,
    -            confirmed,
    +    pub fn get_balance(&self) -> Balance {
    +        self.keychain_tracker.balance(|keychain| match keychain {
    +            KeychainKind::External => false,
    +            KeychainKind::Internal => true,
             })
         }
     
    @@ -6110,8 +2361,7 @@
         /// ```
         /// # use bdk::{Wallet, KeychainKind};
         /// # use bdk::bitcoin::Network;
    -    /// # use bdk::database::MemoryDatabase;
    -    /// let wallet = Wallet::new("wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*)", None, Network::Testnet, MemoryDatabase::new())?;
    +    /// let wallet = Wallet::new_no_persist("wpkh(tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*)", None, Network::Testnet)?;
         /// for secret_key in wallet.get_signers(KeychainKind::External).signers().iter().filter_map(|s| s.descriptor_secret_key()) {
         ///     // secret_key: tprv8ZgxMBicQKsPe73PBRSmNbTfbcsZnwWhz5eVmhHpi31HW29Z7mc9B4cWGRQzopNUzZUT391DeDJxL2PefNunWyLgqCKRMDkU1s2s8bAfoSk/84'/0'/0'/0/*
         ///     println!("secret_key: {}", secret_key);
    @@ -6136,9 +2386,8 @@
         /// # use std::str::FromStr;
         /// # use bitcoin::*;
         /// # use bdk::*;
    -    /// # use bdk::database::*;
         /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet = doctest_wallet!();
    +    /// # let mut wallet = doctest_wallet!();
         /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
         /// let (psbt, details) = {
         ///    let mut builder =  wallet.build_tx();
    @@ -6152,26 +2401,39 @@
         /// ```
         ///
         /// [`TxBuilder`]: crate::TxBuilder
    -    pub fn build_tx(&self) -> TxBuilder<'_, D, DefaultCoinSelectionAlgorithm, CreateTx> {
    +    pub fn build_tx(&mut self) -> TxBuilder<'_, D, DefaultCoinSelectionAlgorithm, CreateTx> {
             TxBuilder {
    -            wallet: self,
    +            wallet: alloc::rc::Rc::new(core::cell::RefCell::new(self)),
                 params: TxParams::default(),
                 coin_selection: DefaultCoinSelectionAlgorithm::default(),
                 phantom: core::marker::PhantomData,
             }
         }
     
    -    pub(crate) fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm<D>>(
    -        &self,
    +    pub(crate) fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm>(
    +        &mut self,
             coin_selection: Cs,
             params: TxParams,
    -    ) -> Result<(psbt::PartiallySignedTransaction, TransactionDetails), Error> {
    -        let external_policy = self
    -            .descriptor
    +    ) -> Result<(psbt::PartiallySignedTransaction, TransactionDetails), Error>
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
    +        let external_descriptor = self
    +            .keychain_tracker
    +            .txout_index
    +            .keychains()
    +            .get(&KeychainKind::External)
    +            .expect("must exist");
    +        let internal_descriptor = self
    +            .keychain_tracker
    +            .txout_index
    +            .keychains()
    +            .get(&KeychainKind::Internal);
    +
    +        let external_policy = external_descriptor
                 .extract_policy(&self.signers, BuildSatisfaction::None, &self.secp)?
                 .unwrap();
    -        let internal_policy = self
    -            .change_descriptor
    +        let internal_policy = internal_descriptor
                 .as_ref()
                 .map(|desc| {
                     Ok::<_, Error>(
    @@ -6240,9 +2502,12 @@
             // We use a match here instead of a map_or_else as it's way more readable :)
             let current_height = match params.current_height {
                 // If they didn't tell us the current height, we assume it's the latest sync height.
    -            None => self.database().get_sync_time()?.map(|sync_time| {
    -                LockTime::from_height(sync_time.block_time.height).expect("Invalid height")
    -            }),
    +            None => self
    +                .keychain_tracker
    +                .chain()
    +                .latest_checkpoint()
    +                .and_then(|cp| cp.height.into())
    +                .map(|height| LockTime::from_height(height).expect("Invalid height")),
                 h => h,
             };
     
    @@ -6362,7 +2627,7 @@
                     return Err(Error::OutputBelowDustLimit(index));
                 }
     
    -            if self.is_mine(script_pubkey)? {
    +            if self.is_mine(script_pubkey) {
                     received += value;
                 }
     
    @@ -6390,7 +2655,7 @@
             fee_amount += fee_rate.fee_wu(2);
     
             if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
    -            && self.change_descriptor.is_none()
    +            && internal_descriptor.is_none()
             {
                 return Err(Error::Generic(
                     "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
    @@ -6405,19 +2670,28 @@
                 params.manually_selected_only,
                 params.bumping_fee.is_some(), // we mandate confirmed transactions if we're bumping the fee
                 current_height.map(LockTime::to_consensus_u32),
    -        )?;
    +        );
     
             // get drain script
             let drain_script = match params.drain_to {
                 Some(ref drain_recipient) => drain_recipient.clone(),
    -            None => self
    -                .get_internal_address(AddressIndex::New)?
    -                .address
    -                .script_pubkey(),
    +            None => {
    +                let change_keychain = self.map_keychain(KeychainKind::Internal);
    +                let ((index, spk), changeset) = self
    +                    .keychain_tracker
    +                    .txout_index
    +                    .next_unused_spk(&change_keychain);
    +                let spk = spk.clone();
    +                self.keychain_tracker
    +                    .txout_index
    +                    .mark_used(&change_keychain, index);
    +                self.persist.stage(changeset.into());
    +                self.persist.commit().expect("TODO");
    +                spk
    +            }
             };
     
             let coin_selection = coin_selection.coin_select(
    -            self.database.borrow().deref(),
                 required_utxos,
                 optional_utxos,
                 fee_rate,
    @@ -6468,7 +2742,7 @@
                     remaining_amount, ..
                 } => fee_amount += remaining_amount,
                 Change { amount, fee } => {
    -                if self.is_mine(&drain_script)? {
    +                if self.is_mine(&drain_script) {
                         received += amount;
                     }
                     fee_amount += fee;
    @@ -6496,7 +2770,7 @@
             let transaction_details = TransactionDetails {
                 transaction: None,
                 txid,
    -            confirmation_time: None,
    +            confirmation_time: ConfirmationTime::Unconfirmed,
                 received,
                 sent,
                 fee: Some(fee_amount),
    @@ -6518,9 +2792,8 @@
         /// # use std::str::FromStr;
         /// # use bitcoin::*;
         /// # use bdk::*;
    -    /// # use bdk::database::*;
         /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet = doctest_wallet!();
    +    /// # let mut wallet = doctest_wallet!();
         /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
         /// let (mut psbt, _) = {
         ///     let mut builder = wallet.build_tx();
    @@ -6546,16 +2819,20 @@
         /// ```
         // TODO: support for merging multiple transactions while bumping the fees
         pub fn build_fee_bump(
    -        &self,
    +        &mut self,
             txid: Txid,
         ) -> Result<TxBuilder<'_, D, DefaultCoinSelectionAlgorithm, BumpFee>, Error> {
    -        let mut details = match self.database.borrow().get_tx(&txid, true)? {
    +        let graph = self.keychain_tracker.graph();
    +        let txout_index = &self.keychain_tracker.txout_index;
    +        let tx_and_height = self.keychain_tracker.chain_graph().get_tx_in_chain(txid);
    +        let mut tx = match tx_and_height {
                 None => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.confirmation_time.is_some() => return Err(Error::TransactionConfirmed),
    -            Some(tx) => tx,
    +            Some((ConfirmationTime::Confirmed { .. }, _tx)) => {
    +                return Err(Error::TransactionConfirmed)
    +            }
    +            Some((_, tx)) => tx.clone(),
             };
    -        let mut tx = details.transaction.take().unwrap();
    +
             if !tx
                 .input
                 .iter()
    @@ -6564,64 +2841,71 @@
                 return Err(Error::IrreplaceableTransaction);
             }
     
    -        let feerate = FeeRate::from_wu(details.fee.ok_or(Error::FeeRateUnavailable)?, tx.weight());
    +        let fee = graph.calculate_fee(&tx).ok_or(Error::FeeRateUnavailable)?;
    +        if fee < 0 {
    +            // It's available but it's wrong so let's say it's unavailable
    +            return Err(Error::FeeRateUnavailable)?;
    +        }
    +        let fee = fee as u64;
    +        let feerate = FeeRate::from_wu(fee, tx.weight());
     
             // remove the inputs from the tx and process them
             let original_txin = tx.input.drain(..).collect::<Vec<_>>();
             let original_utxos = original_txin
                 .iter()
                 .map(|txin| -> Result<_, Error> {
    -                let txout = self
    -                    .database
    -                    .borrow()
    -                    .get_previous_output(&txin.previous_output)?
    -                    .ok_or(Error::UnknownUtxo)?;
    -
    -                let (weight, keychain) = match self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&txout.script_pubkey)?
    -                {
    -                    Some((keychain, _)) => (
    -                        self._get_descriptor_for_keychain(keychain)
    -                            .0
    -                            .max_satisfaction_weight()
    -                            .unwrap(),
    -                        keychain,
    -                    ),
    +                let (&confirmation_time, prev_tx) = self
    +                    .keychain_tracker
    +                    .chain_graph()
    +                    .get_tx_in_chain(txin.previous_output.txid)
    +                    .ok_or(Error::UnknownUtxo)?;
    +                let txout = &prev_tx.output[txin.previous_output.vout as usize];
    +
    +                let weighted_utxo = match txout_index.index_of_spk(&txout.script_pubkey) {
    +                    Some(&(keychain, derivation_index)) => {
    +                        let satisfaction_weight = self
    +                            .get_descriptor_for_keychain(keychain)
    +                            .max_satisfaction_weight()
    +                            .unwrap();
    +                        WeightedUtxo {
    +                            utxo: Utxo::Local(LocalUtxo {
    +                                outpoint: txin.previous_output,
    +                                txout: txout.clone(),
    +                                keychain,
    +                                is_spent: true,
    +                                derivation_index,
    +                                confirmation_time,
    +                            }),
    +                            satisfaction_weight,
    +                        }
    +                    }
                         None => {
    -                        // estimate the weight based on the scriptsig/witness size present in the
    -                        // original transaction
    -                        let weight =
    +                        let satisfaction_weight =
                                 serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
    -                        (weight, KeychainKind::External)
    +                        WeightedUtxo {
    +                            satisfaction_weight,
    +                            utxo: Utxo::Foreign {
    +                                outpoint: txin.previous_output,
    +                                psbt_input: Box::new(psbt::Input {
    +                                    witness_utxo: Some(txout.clone()),
    +                                    non_witness_utxo: Some(prev_tx.clone()),
    +                                    ..Default::default()
    +                                }),
    +                            },
    +                        }
                         }
                     };
     
    -                let utxo = LocalUtxo {
    -                    outpoint: txin.previous_output,
    -                    txout,
    -                    keychain,
    -                    is_spent: true,
    -                };
    -
    -                Ok(WeightedUtxo {
    -                    satisfaction_weight: weight,
    -                    utxo: Utxo::Local(utxo),
    -                })
    +                Ok(weighted_utxo)
                 })
                 .collect::<Result<Vec<_>, _>>()?;
     
             if tx.output.len() > 1 {
                 let mut change_index = None;
                 for (index, txout) in tx.output.iter().enumerate() {
    -                let (_, change_type) = self._get_descriptor_for_keychain(KeychainKind::Internal);
    -                match self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&txout.script_pubkey)?
    -                {
    -                    Some((keychain, _)) if keychain == change_type => change_index = Some(index),
    +                let change_type = self.map_keychain(KeychainKind::Internal);
    +                match txout_index.index_of_spk(&txout.script_pubkey) {
    +                    Some(&(keychain, _)) if keychain == change_type => change_index = Some(index),
                         _ => {}
                     }
                 }
    @@ -6641,14 +2925,14 @@
                     .collect(),
                 utxos: original_utxos,
                 bumping_fee: Some(tx_builder::PreviousFee {
    -                absolute: details.fee.ok_or(Error::FeeRateUnavailable)?,
    +                absolute: fee,
                     rate: feerate.as_sat_per_vb(),
                 }),
                 ..Default::default()
             };
     
             Ok(TxBuilder {
    -            wallet: self,
    +            wallet: alloc::rc::Rc::new(core::cell::RefCell::new(self)),
                 params,
                 coin_selection: DefaultCoinSelectionAlgorithm::default(),
                 phantom: core::marker::PhantomData,
    @@ -6669,9 +2953,8 @@
         /// # use std::str::FromStr;
         /// # use bitcoin::*;
         /// # use bdk::*;
    -    /// # use bdk::database::*;
         /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet = doctest_wallet!();
    +    /// # let mut wallet = doctest_wallet!();
         /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
         /// let (mut psbt, _) = {
         ///     let mut builder = wallet.build_tx();
    @@ -6735,18 +3018,14 @@
     
         /// Return the spending policies for the wallet's descriptor
         pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, Error> {
    -        match (keychain, self.change_descriptor.as_ref()) {
    -            (KeychainKind::External, _) => Ok(self.descriptor.extract_policy(
    -                &self.signers,
    -                BuildSatisfaction::None,
    -                &self.secp,
    -            )?),
    -            (KeychainKind::Internal, None) => Ok(None),
    -            (KeychainKind::Internal, Some(desc)) => Ok(desc.extract_policy(
    -                &self.change_signers,
    -                BuildSatisfaction::None,
    -                &self.secp,
    -            )?),
    +        let signers = match keychain {
    +            KeychainKind::External => &self.signers,
    +            KeychainKind::Internal => &self.change_signers,
    +        };
    +
    +        match self.public_descriptor(keychain) {
    +            Some(desc) => Ok(desc.extract_policy(signers, BuildSatisfaction::None, &self.secp)?),
    +            None => Ok(None),
             }
         }
     
    @@ -6754,15 +3033,8 @@
         /// the same structure but with every secret key removed
         ///
         /// This can be used to build a watch-only version of a wallet
    -    pub fn public_descriptor(
    -        &self,
    -        keychain: KeychainKind,
    -    ) -> Result<Option<ExtendedDescriptor>, Error> {
    -        match (keychain, self.change_descriptor.as_ref()) {
    -            (KeychainKind::External, _) => Ok(Some(self.descriptor.clone())),
    -            (KeychainKind::Internal, None) => Ok(None),
    -            (KeychainKind::Internal, Some(desc)) => Ok(Some(desc.clone())),
    -        }
    +    pub fn public_descriptor(&self, keychain: KeychainKind) -> Option<&ExtendedDescriptor> {
    +        self.keychain_tracker.txout_index.keychains().get(&keychain)
         }
     
         /// Finalize a PSBT, i.e., for each input determine if sufficient data is available to pass
    @@ -6789,22 +3061,24 @@
                 if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
                     continue;
                 }
    -            // if the height is None in the database it means it's still unconfirmed, so consider
    -            // that as a very high value
    -            let create_height = self
    -                .database
    -                .borrow()
    -                .get_tx(&input.previous_output.txid, false)?
    -                .map(|tx| tx.confirmation_time.map(|c| c.height).unwrap_or(u32::MAX));
    +            let confirmation_height = self
    +                .keychain_tracker
    +                .chain()
    +                .tx_position(input.previous_output.txid)
    +                .map(|conftime| match conftime {
    +                    &ConfirmationTime::Confirmed { height, .. } => height,
    +                    ConfirmationTime::Unconfirmed => u32::MAX,
    +                });
                 let last_sync_height = self
    -                .database()
    -                .get_sync_time()?
    -                .map(|sync_time| sync_time.block_time.height);
    +                .keychain_tracker
    +                .chain()
    +                .latest_checkpoint()
    +                .map(|block_id| block_id.height);
                 let current_height = sign_options.assume_height.or(last_sync_height);
     
                 debug!(
    -                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
    -                n, input.previous_output, create_height, current_height
    +                "Input #{} - {}, using `confirmation_height` = {:?}, `current_height` = {:?}",
    +                n, input.previous_output, confirmation_height, current_height
                 );
     
                 // - Try to derive the descriptor by looking at the txout. If it's in our database, we
    @@ -6815,20 +3089,19 @@
                 // - If that also fails, it will try it on the internal descriptor, if present
                 let desc = psbt
                     .get_utxo_for(n)
    -                .map(|txout| self.get_descriptor_for_txout(&txout))
    -                .transpose()?
    -                .flatten()
    +                .and_then(|txout| self.get_descriptor_for_txout(&txout))
                     .or_else(|| {
    -                    self.descriptor.derive_from_psbt_input(
    -                        psbt_input,
    -                        psbt.get_utxo_for(n),
    -                        &self.secp,
    -                    )
    -                })
    -                .or_else(|| {
    -                    self.change_descriptor.as_ref().and_then(|desc| {
    -                        desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n), &self.secp)
    -                    })
    +                    self.keychain_tracker
    +                        .txout_index
    +                        .keychains()
    +                        .iter()
    +                        .find_map(|(_, desc)| {
    +                            desc.derive_from_psbt_input(
    +                                psbt_input,
    +                                psbt.get_utxo_for(n),
    +                                &self.secp,
    +                            )
    +                        })
                     });
     
                 match desc {
    @@ -6839,7 +3112,7 @@
                             (
                                 PsbtInputSatisfier::new(psbt, n),
                                 After::new(current_height, false),
    -                            Older::new(current_height, create_height, false),
    +                            Older::new(current_height, confirmation_height, false),
                             ),
                         ) {
                             Ok(_) => {
    @@ -6870,114 +3143,60 @@
     
         /// Returns the descriptor used to create addresses for a particular `keychain`.
         pub fn get_descriptor_for_keychain(&self, keychain: KeychainKind) -> &ExtendedDescriptor {
    -        let (descriptor, _) = self._get_descriptor_for_keychain(keychain);
    -        descriptor
    -    }
    -
    -    // Internals
    -
    -    fn _get_descriptor_for_keychain(
    -        &self,
    -        keychain: KeychainKind,
    -    ) -> (&ExtendedDescriptor, KeychainKind) {
    -        match keychain {
    -            KeychainKind::Internal if self.change_descriptor.is_some() => (
    -                self.change_descriptor.as_ref().unwrap(),
    -                KeychainKind::Internal,
    -            ),
    -            _ => (&self.descriptor, KeychainKind::External),
    -        }
    +        self.public_descriptor(self.map_keychain(keychain))
    +            .expect("we mapped it to external if it doesn't exist")
         }
     
    -    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<DerivedDescriptor>, Error> {
    -        Ok(self
    -            .database
    -            .borrow()
    -            .get_path_from_script_pubkey(&txout.script_pubkey)?
    -            .map(|(keychain, child)| (self.get_descriptor_for_keychain(keychain), child))
    -            .map(|(desc, child)| desc.at_derivation_index(child)))
    +    /// The derivation index of this wallet. It will return `None` if it has not derived any addresses.
    +    /// Otherwise, it will return the index of the highest address it has derived.
    +    pub fn derivation_index(&self, keychain: KeychainKind) -> Option<u32> {
    +        self.keychain_tracker
    +            .txout_index
    +            .last_revealed_index(&keychain)
         }
     
    -    fn fetch_and_increment_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
    -        let index = match descriptor.has_wildcard() {
    -            false => 0,
    -            true => self.database.borrow_mut().increment_last_index(keychain)?,
    -        };
    +    /// The index of the next address that you would get if you were to ask the wallet for a new address
    +    pub fn next_derivation_index(&self, keychain: KeychainKind) -> u32 {
    +        self.keychain_tracker.txout_index.next_index(&keychain).0
    +    }
     
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(keychain, index)?
    -            .is_none()
    -        {
    -            self.cache_addresses(keychain, index, CACHE_ADDR_BATCH_SIZE)?;
    +    /// Informs the wallet that you no longer intend to broadcast a tx that was built from it.
    +    ///
    +    /// This frees up the change address used when creating the tx for use in future transactions.
    +    // TODO: Make this free up reserved utxos when that's implemented
    +    pub fn cancel_tx(&mut self, tx: &Transaction) {
    +        let txout_index = &mut self.keychain_tracker.txout_index;
    +        for txout in &tx.output {
    +            if let Some(&(keychain, index)) = txout_index.index_of_spk(&txout.script_pubkey) {
    +                // NOTE: unmark_used will **not** make something unused if it has actually been used
    +                // by a tx in the tracker. It only removes the superficial marking.
    +                txout_index.unmark_used(&keychain, index);
    +            }
             }
    -
    -        Ok(index)
         }
     
    -    fn fetch_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
    -        let index = match descriptor.has_wildcard() {
    -            false => Some(0),
    -            true => self.database.borrow_mut().get_last_index(keychain)?,
    -        };
    -
    -        if let Some(i) = index {
    -            Ok(i)
    +    fn map_keychain(&self, keychain: KeychainKind) -> KeychainKind {
    +        if keychain == KeychainKind::Internal
    +            && self.public_descriptor(KeychainKind::Internal).is_none()
    +        {
    +            KeychainKind::External
             } else {
    -            self.fetch_and_increment_index(keychain)
    +            keychain
             }
         }
     
    -    fn set_index(&self, keychain: KeychainKind, index: u32) -> Result<(), Error> {
    -        self.database.borrow_mut().set_last_index(keychain, index)?;
    -        Ok(())
    -    }
    -
    -    fn cache_addresses(
    -        &self,
    -        keychain: KeychainKind,
    -        from: u32,
    -        mut count: u32,
    -    ) -> Result<(), Error> {
    -        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
    -        if !descriptor.has_wildcard() {
    -            if from > 0 {
    -                return Ok(());
    -            }
    -
    -            count = 1;
    -        }
    -
    -        let mut address_batch = self.database.borrow().begin_batch();
    -
    -        let start_time = time::Instant::new();
    -        for i in from..(from + count) {
    -            address_batch.set_script_pubkey(
    -                &descriptor.at_derivation_index(i).script_pubkey(),
    -                keychain,
    -                i,
    -            )?;
    -        }
    -
    -        info!(
    -            "Derivation of {} addresses from {} took {} ms",
    -            count,
    -            from,
    -            start_time.elapsed().as_millis()
    -        );
    -
    -        self.database.borrow_mut().commit_batch(address_batch)?;
    -
    -        Ok(())
    +    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Option<DerivedDescriptor> {
    +        let &(keychain, child) = self
    +            .keychain_tracker
    +            .txout_index
    +            .index_of_spk(&txout.script_pubkey)?;
    +        let descriptor = self.get_descriptor_for_keychain(keychain);
    +        Some(descriptor.at_derivation_index(child))
         }
     
    -    fn get_available_utxos(&self) -> Result<Vec<(LocalUtxo, usize)>, Error> {
    -        Ok(self
    -            .list_unspent()?
    -            .into_iter()
    +    fn get_available_utxos(&self) -> Vec<(LocalUtxo, usize)> {
    +        self.list_unspent()
    +            .into_iter()
                 .map(|utxo| {
                     let keychain = utxo.keychain;
                     (
    @@ -6987,13 +3206,12 @@
                             .unwrap(),
                     )
                 })
    -            .collect())
    +            .collect()
         }
     
         /// Given the options returns the list of utxos that must be used to form the
         /// transaction and any further that may be used if needed.
    -    #[allow(clippy::type_complexity)]
    -    #[allow(clippy::too_many_arguments)]
    +    #[allow(clippy::too_many_arguments)]
         fn preselect_utxos(
             &self,
             change_policy: tx_builder::ChangeSpendPolicy,
    @@ -7003,10 +3221,10 @@
             manual_only: bool,
             must_only_use_confirmed_tx: bool,
             current_height: Option<u32>,
    -    ) -> Result<(Vec<WeightedUtxo>, Vec<WeightedUtxo>), Error> {
    +    ) -> (Vec<WeightedUtxo>, Vec<WeightedUtxo>) {
             //    must_spend <- manually selected utxos
             //    may_spend  <- all other available utxos
    -        let mut may_spend = self.get_available_utxos()?;
    +        let mut may_spend = self.get_available_utxos();
     
             may_spend.retain(|may_spend| {
                 !manually_selected
    @@ -7018,47 +3236,46 @@
             // NOTE: we are intentionally ignoring `unspendable` here. i.e manual
             // selection overrides unspendable.
             if manual_only {
    -            return Ok((must_spend, vec![]));
    +            return (must_spend, vec![]);
             }
     
    -        let database = self.database.borrow();
             let satisfies_confirmed = may_spend
                 .iter()
                 .map(|u| {
    -                database
    -                    .get_tx(&u.0.outpoint.txid, true)
    -                    .map(|tx| match tx {
    -                        // We don't have the tx in the db for some reason,
    -                        // so we can't know for sure if it's mature or not.
    -                        // We prefer not to spend it.
    -                        None => false,
    -                        Some(tx) => {
    -                            // Whether the UTXO is mature and, if needed, confirmed
    -                            let mut spendable = true;
    -                            if must_only_use_confirmed_tx && tx.confirmation_time.is_none() {
    -                                return false;
    -                            }
    -                            if tx
    -                                .transaction
    -                                .expect("We specifically ask for the transaction above")
    -                                .is_coin_base()
    -                            {
    -                                if let Some(current_height) = current_height {
    -                                    match &tx.confirmation_time {
    -                                        Some(t) => {
    -                                            // https://github.com/bitcoin/bitcoin/blob/c5e67be03bb06a5d7885c55db1f016fbf2333fe3/src/validation.cpp#L373-L375
    -                                            spendable &= (current_height.saturating_sub(t.height))
    -                                                >= COINBASE_MATURITY;
    -                                        }
    -                                        None => spendable = false,
    +                let txid = u.0.outpoint.txid;
    +                let tx = self.keychain_tracker.chain_graph().get_tx_in_chain(txid);
    +                match tx {
    +                    // We don't have the tx in the db for some reason,
    +                    // so we can't know for sure if it's mature or not.
    +                    // We prefer not to spend it.
    +                    None => false,
    +                    Some((confirmation_time, tx)) => {
    +                        // Whether the UTXO is mature and, if needed, confirmed
    +                        let mut spendable = true;
    +                        if must_only_use_confirmed_tx && !confirmation_time.is_confirmed() {
    +                            return false;
    +                        }
    +                        if tx.is_coin_base() {
    +                            debug_assert!(
    +                                confirmation_time.is_confirmed(),
    +                                "coinbase must always be confirmed"
    +                            );
    +                            if let Some(current_height) = current_height {
    +                                match confirmation_time {
    +                                    ConfirmationTime::Confirmed { height, .. } => {
    +                                        // https://github.com/bitcoin/bitcoin/blob/c5e67be03bb06a5d7885c55db1f016fbf2333fe3/src/validation.cpp#L373-L375
    +                                        spendable &= (current_height.saturating_sub(*height))
    +                                            >= COINBASE_MATURITY;
                                         }
    +                                    ConfirmationTime::Unconfirmed => spendable = false,
                                     }
                                 }
    -                            spendable
                             }
    -                    })
    +                        spendable
    +                    }
    +                }
                 })
    -            .collect::<Result<Vec<_>, _>>()?;
    +            .collect::<Vec<_>>();
     
             let mut i = 0;
             may_spend.retain(|u| {
    @@ -7081,7 +3298,7 @@
                 must_spend.append(&mut may_spend);
             }
     
    -        Ok((must_spend, may_spend))
    +        (must_spend, may_spend)
         }
     
         fn complete_transaction(
    @@ -7093,10 +3310,11 @@
             let mut psbt = psbt::PartiallySignedTransaction::from_unsigned_tx(tx)?;
     
             if params.add_global_xpubs {
    -            let mut all_xpubs = self.descriptor.get_extended_keys()?;
    -            if let Some(change_descriptor) = &self.change_descriptor {
    -                all_xpubs.extend(change_descriptor.get_extended_keys()?);
    -            }
    +            let all_xpubs = self
    +                .keychanins()
    +                .iter()
    +                .flat_map(|(_, desc)| desc.get_extended_keys())
    +                .collect::<Vec<_>>();
     
                 for xpub in all_xpubs {
                     let origin = match xpub.origin {
    @@ -7174,11 +3392,11 @@
         ) -> Result<psbt::Input, Error> {
             // Try to find the prev_script in our db to figure out if this is internal or external,
             // and the derivation index
    -        let (keychain, child) = self
    -            .database
    -            .borrow()
    -            .get_path_from_script_pubkey(&utxo.txout.script_pubkey)?
    -            .ok_or(Error::UnknownUtxo)?;
    +        let &(keychain, child) = self
    +            .keychain_tracker
    +            .txout_index
    +            .index_of_spk(&utxo.txout.script_pubkey)
    +            .ok_or(Error::UnknownUtxo)?;
     
             let mut psbt_input = psbt::Input {
                 sighash_type,
    @@ -7193,12 +3411,12 @@
                 .map_err(MiniscriptPsbtError::Conversion)?;
     
             let prev_output = utxo.outpoint;
    -        if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
    +        if let Some(prev_tx) = self.keychain_tracker.graph().get_tx(prev_output.txid) {
                 if desc.is_witness() || desc.is_taproot() {
                     psbt_input.witness_utxo = Some(prev_tx.output[prev_output.vout as usize].clone());
                 }
                 if !desc.is_taproot() && (!desc.is_witness() || !only_witness_utxo) {
    -                psbt_input.non_witness_utxo = Some(prev_tx);
    +                psbt_input.non_witness_utxo = Some(prev_tx.clone());
                 }
             }
             Ok(psbt_input)
    @@ -7226,11 +3444,11 @@
     
             // Try to figure out the keychain and derivation for every input and output
             for (is_input, index, out) in utxos.into_iter() {
    -            if let Some((keychain, child)) = self
    -                .database
    -                .borrow()
    -                .get_path_from_script_pubkey(&out.script_pubkey)?
    -            {
    +            if let Some(&(keychain, child)) = self
    +                .keychain_tracker
    +                .txout_index
    +                .index_of_spk(&out.script_pubkey)
    +            {
                     debug!(
                         "Found descriptor for input #{} {:?}/{}",
                         index, keychain, child
    @@ -7252,87 +3470,6 @@
             Ok(())
         }
     
    -    /// Return an immutable reference to the internal database
    -    pub fn database(&self) -> impl std::ops::Deref<Target = D> + '_ {
    -        self.database.borrow()
    -    }
    -
    -    /// Sync the internal database with the blockchain
    -    #[maybe_async]
    -    pub fn sync<B: WalletSync + GetHeight>(
    -        &self,
    -        blockchain: &B,
    -        sync_opts: SyncOptions,
    -    ) -> Result<(), Error> {
    -        debug!("Begin sync...");
    -
    -        // TODO: for the next runs, we cannot reuse the `sync_opts.progress` object due to trait
    -        // restrictions
    -        let mut progress_iter = sync_opts.progress.into_iter();
    -        let mut new_progress = || {
    -            progress_iter
    -                .next()
    -                .unwrap_or_else(|| Box::new(NoopProgress))
    -        };
    -
    -        let run_setup = self.ensure_addresses_cached(CACHE_ADDR_BATCH_SIZE)?;
    -        debug!("run_setup: {}", run_setup);
    -
    -        // TODO: what if i generate an address first and cache some addresses?
    -        // TODO: we should sync if generating an address triggers a new batch to be stored
    -
    -        // We need to ensure descriptor is derivable to fullfil "missing cache", otherwise we will
    -        // end up with an infinite loop
    -        let has_wildcard = self.descriptor.has_wildcard()
    -            && (self.change_descriptor.is_none()
    -                || self.change_descriptor.as_ref().unwrap().has_wildcard());
    -
    -        // Restrict max rounds in case of faulty "missing cache" implementation by blockchain
    -        let max_rounds = if has_wildcard { 100 } else { 1 };
    -
    -        for _ in 0..max_rounds {
    -            let sync_res = if run_setup {
    -                maybe_await!(blockchain.wallet_setup(&self.database, new_progress()))
    -            } else {
    -                maybe_await!(blockchain.wallet_sync(&self.database, new_progress()))
    -            };
    -
    -            // If the error is the special `MissingCachedScripts` error, we return the number of
    -            // scripts we should ensure cached.
    -            // On any other error, we should return the error.
    -            // On no error, we say `ensure_cache` is 0.
    -            let ensure_cache = sync_res.map_or_else(
    -                |e| match e {
    -                    Error::MissingCachedScripts(inner) => {
    -                        // each call to `WalletSync` is expensive, maximize on scripts to search for
    -                        let extra =
    -                            std::cmp::max(inner.missing_count as u32, CACHE_ADDR_BATCH_SIZE);
    -                        let last = inner.last_count as u32;
    -                        Ok(extra + last)
    -                    }
    -                    _ => Err(e),
    -                },
    -                |_| Ok(0_u32),
    -            )?;
    -
    -            // cache and try again, break when there is nothing to cache
    -            if !self.ensure_addresses_cached(ensure_cache)? {
    -                break;
    -            }
    -        }
    -
    -        let sync_time = SyncTime {
    -            block_time: BlockTime {
    -                height: maybe_await!(blockchain.get_height())?,
    -                timestamp: time::get_timestamp(),
    -            },
    -        };
    -        debug!("Saving `sync_time` = {:?}", sync_time);
    -        self.database.borrow_mut().set_sync_time(sync_time)?;
    -
    -        Ok(())
    -    }
    -
         /// Return the checksum of the public descriptor associated to `keychain`
         ///
         /// Internally calls [`Self::get_descriptor_for_keychain`] to fetch the right descriptor
    @@ -7344,6 +3481,60 @@
                 .1
                 .to_string()
         }
    +
    +    /// Applies an update to the wallet and stages the changes (but does not [`commit`] them).
    +    ///
    +    /// Usually you create an `update` by interacting with some blockchain data source and inserting
    +    /// transactions related to your wallet into it.
    +    ///
    +    /// [`commit`]: Self::commit
    +    pub fn apply_update(&mut self, update: Update) -> Result<(), UpdateError>
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
    +        let changeset = self.keychain_tracker.apply_update(update)?;
    +        self.persist.stage(changeset);
    +        Ok(())
    +    }
    +
    +    /// Commits all curently [`staged`] changed to the persistence backend returning and error when this fails.
    +    ///
    +    /// [`staged`]: Self::staged
    +    pub fn commit(&mut self) -> Result<(), D::WriteError>
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
    +        self.persist.commit()
    +    }
    +
    +    /// Returns the changes that will be staged with the next call to [`commit`].
    +    ///
    +    /// [`commit`]: Self::commit
    +    pub fn staged(&self) -> &ChangeSet {
    +        self.persist.staged()
    +    }
    +
    +    /// Get a reference to the inner [`TxGraph`](bdk_chain::tx_graph::TxGraph).
    +    pub fn as_graph(&self) -> &bdk_chain::tx_graph::TxGraph {
    +        self.keychain_tracker.graph()
    +    }
    +
    +    /// Get a reference to the inner [`ChainGraph`](bdk_chain::chain_graph::ChainGraph).
    +    pub fn as_chain_graph(&self) -> &bdk_chain::chain_graph::ChainGraph<ConfirmationTime> {
    +        self.keychain_tracker.chain_graph()
    +    }
    +}
    +
    +impl<D> AsRef<bdk_chain::tx_graph::TxGraph> for Wallet<D> {
    +    fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph {
    +        self.keychain_tracker.graph()
    +    }
    +}
    +
    +impl<D> AsRef<bdk_chain::chain_graph::ChainGraph<ConfirmationTime>> for Wallet<D> {
    +    fn as_ref(&self) -> &bdk_chain::chain_graph::ChainGraph<ConfirmationTime> {
    +        self.keychain_tracker.chain_graph()
    +    }
     }
     
     /// Deterministically generate a unique name given the descriptors defining the wallet
    @@ -7377,3769 +3568,41 @@
         Ok(wallet_name)
     }
     
    -/// Return a fake wallet that appears to be funded for testing.
    -pub fn get_funded_wallet(
    -    descriptor: &str,
    -) -> (Wallet<AnyDatabase>, (String, Option<String>), bitcoin::Txid) {
    -    let descriptors = testutils!(@descriptors (descriptor));
    -    let wallet = Wallet::new(
    -        &descriptors.0,
    -        None,
    -        Network::Regtest,
    -        AnyDatabase::Memory(MemoryDatabase::new()),
    -    )
    -    .unwrap();
    -
    -    let funding_address_kix = 0;
    -
    -    let tx_meta = testutils! {
    -            @tx ( (@external descriptors, funding_address_kix) => 50_000 ) (@confirmations 1)
    -    };
    -
    -    wallet
    -        .database
    -        .borrow_mut()
    -        .set_script_pubkey(
    -            &bitcoin::Address::from_str(&tx_meta.output.get(0).unwrap().to_address)
    -                .unwrap()
    -                .script_pubkey(),
    -            KeychainKind::External,
    -            funding_address_kix,
    -        )
    -        .unwrap();
    -    wallet
    -        .database
    -        .borrow_mut()
    -        .set_last_index(KeychainKind::External, funding_address_kix)
    -        .unwrap();
    -
    -    let txid = crate::populate_test_db!(wallet.database.borrow_mut(), tx_meta, Some(100));
    -
    -    (wallet, descriptors, txid)
    -}
    -
    -#[cfg(test)]
    -pub(crate) mod test {
    -    use assert_matches::assert_matches;
    -    use bitcoin::{util::psbt, Network, PackedLockTime, Sequence};
    -
    -    use crate::database::Database;
    -    use crate::types::KeychainKind;
    -
    -    use super::*;
    -    use crate::signer::{SignOptions, SignerError};
    -    use crate::wallet::AddressIndex::{LastUnused, New, Peek, Reset};
    -
    -    // The satisfaction size of a P2WPKH is 112 WU =
    -    // 1 (elements in witness) + 1 (OP_PUSH) + 33 (pk) + 1 (OP_PUSH) + 72 (signature + sighash) + 1*4 (script len)
    -    // On the witness itself, we have to push once for the pk (33WU) and once for signature + sighash (72WU), for
    -    // a total of 105 WU.
    -    // Here, we push just once for simplicity, so we have to add an extra byte for the missing
    -    // OP_PUSH.
    -    const P2WPKH_FAKE_WITNESS_SIZE: usize = 106;
    -
    -    #[test]
    -    fn test_descriptor_checksum() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let checksum = wallet.descriptor_checksum(KeychainKind::External);
    -        assert_eq!(checksum.len(), 8);
    -        assert_eq!(
    -            calc_checksum(&wallet.descriptor.to_string()).unwrap(),
    -            checksum
    -        );
    -    }
    -
    -    #[test]
    -    fn test_db_checksum() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let desc = wallet.descriptor.to_string();
    -
    -        let checksum = calc_checksum_bytes_internal(&desc, true).unwrap();
    -        let checksum_inception = calc_checksum_bytes_internal(&desc, false).unwrap();
    -        let checksum_invalid = [b'q'; 8];
    -
    -        let mut db = MemoryDatabase::new();
    -        db.check_descriptor_checksum(KeychainKind::External, checksum)
    -            .expect("failed to save actual checksum");
    -        Wallet::db_checksum(&mut db, &desc, KeychainKind::External)
    -            .expect("db that uses actual checksum should be supported");
    -
    -        let mut db = MemoryDatabase::new();
    -        db.check_descriptor_checksum(KeychainKind::External, checksum_inception)
    -            .expect("failed to save checksum inception");
    -        Wallet::db_checksum(&mut db, &desc, KeychainKind::External)
    -            .expect("db that uses checksum inception should be supported");
    -
    -        let mut db = MemoryDatabase::new();
    -        db.check_descriptor_checksum(KeychainKind::External, checksum_invalid)
    -            .expect("failed to save invalid checksum");
    -        Wallet::db_checksum(&mut db, &desc, KeychainKind::External)
    -            .expect_err("db that uses invalid checksum should fail");
    -    }
    -
    -    #[test]
    -    fn test_get_funded_wallet_balance() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        assert_eq!(wallet.get_balance().unwrap().confirmed, 50000);
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses_fixed() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new(
    -            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
    -            None,
    -            Network::Testnet,
    -            db,
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, 0)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::Internal, 0)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses_refill() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -
    -        for _ in 0..CACHE_ADDR_BATCH_SIZE {
    -            wallet.get_address(New).unwrap();
    -        }
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
    -            .unwrap()
    -            .is_some());
    -    }
    -
    -    pub(crate) fn get_test_wpkh() -> &'static str {
    -        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_csv() -> &'static str {
    -        // and(pk(Alice),older(6))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
    -    }
    -
    -    pub(crate) fn get_test_a_or_b_plus_csv() -> &'static str {
    -        // or(pk(Alice),and(pk(Bob),older(144)))
    -        "wsh(or_d(pk(cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu),and_v(v:pk(cMnkdebixpXMPfkcNEjjGin7s94hiehAH4mLbYkZoh9KSiNNmqC8),older(144))))"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
    -        // and(pk(Alice),after(100000))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
    -    }
    -
    -    pub(crate) fn get_test_tr_single_sig() -> &'static str {
    -        "tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG)"
    -    }
    -
    -    pub(crate) fn get_test_tr_with_taptree() -> &'static str {
    -        "tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{pk(cPZzKuNmpuUjD1e8jUU4PVzy2b5LngbSip8mBsxf4e7rSFZVb4Uh),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
    -    }
    -
    -    pub(crate) fn get_test_tr_with_taptree_both_priv() -> &'static str {
    -        "tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{pk(cPZzKuNmpuUjD1e8jUU4PVzy2b5LngbSip8mBsxf4e7rSFZVb4Uh),pk(cNaQCDwmmh4dS9LzCgVtyy1e1xjCJ21GUDHe9K98nzb689JvinGV)})"
    -    }
    -
    -    pub(crate) fn get_test_tr_repeated_key() -> &'static str {
    -        "tr(b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55,{and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100)),and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(200))})"
    -    }
    -
    -    pub(crate) fn get_test_tr_single_sig_xprv() -> &'static str {
    -        "tr(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*)"
    -    }
    -
    -    pub(crate) fn get_test_tr_with_taptree_xprv() -> &'static str {
    -        "tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG,{pk(tprv8ZgxMBicQKsPdDArR4xSAECuVxeX1jwwSXR4ApKbkYgZiziDc4LdBy2WvJeGDfUSE4UT4hHhbgEwbdq8ajjUHiKDegkwrNU6V55CxcxonVN/*),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
    -    }
    -
    -    pub(crate) fn get_test_tr_dup_keys() -> &'static str {
    -        "tr(cNJmN3fH9DDbDt131fQNkVakkpzawJBSeybCUNmP1BovpmGQ45xG,{pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642),pk(8aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642)})"
    -    }
    -
    -    macro_rules! assert_fee_rate {
    -        ($psbt:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
    -            let psbt = $psbt.clone();
    -            #[allow(unused_mut)]
    -            let mut tx = $psbt.clone().extract_tx();
    -            $(
    -                $( $add_signature )*
    -                for txin in &mut tx.input {
    -                    txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -                }
    -            )*
    -
    -            #[allow(unused_mut)]
    -            #[allow(unused_assignments)]
    -            let mut dust_change = false;
    -            $(
    -                $( $dust_change )*
    -                dust_change = true;
    -            )*
    -
    -            let fee_amount = psbt
    -                .inputs
    -                .iter()
    -                .fold(0, |acc, i| acc + i.witness_utxo.as_ref().unwrap().value)
    -                - psbt
    -                    .unsigned_tx
    -                    .output
    -                    .iter()
    -                    .fold(0, |acc, o| acc + o.value);
    -
    -            assert_eq!(fee_amount, $fees);
    -
    -            let tx_fee_rate = FeeRate::from_wu($fees, tx.weight());
    -            let fee_rate = $fee_rate;
    -
    -            if !dust_change {
    -                assert!(tx_fee_rate >= fee_rate && (tx_fee_rate - fee_rate).as_sat_per_vb().abs() < 0.5, "Expected fee rate of {:?}, the tx has {:?}", fee_rate, tx_fee_rate);
    -            } else {
    -                assert!(tx_fee_rate >= fee_rate, "Expected fee rate of at least {:?}, the tx has {:?}", fee_rate, tx_fee_rate);
    -            }
    -        });
    -    }
    -
    -    macro_rules! from_str {
    -        ($e:expr, $t:ty) => {{
    -            use std::str::FromStr;
    -            <$t>::from_str($e).unwrap()
    -        }};
    -
    -        ($e:expr) => {
    -            from_str!($e, _)
    -        };
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoRecipients")]
    -    fn test_create_tx_empty_recipients() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.build_tx().finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoUtxosSelected")]
    -    fn test_create_tx_manually_selected_empty_utxos() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .manually_selected_only();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Invalid version `0`")]
    -    fn test_create_tx_version_0() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .version(0);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
    -    )]
    -    fn test_create_tx_version_1_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .version(1);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_version() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .version(42);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.version, 42);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime() {
    -        let descriptors = testutils!(@descriptors (get_test_wpkh()));
    -        let wallet = Wallet::new(
    -            &descriptors.0,
    -            None,
    +#[macro_export]
    +#[doc(hidden)]
    +/// Macro for getting a wallet for use in a doctest
    +macro_rules! doctest_wallet {
    +    () => {{
    +        use $crate::bitcoin::{BlockHash, Transaction, PackedLockTime, TxOut, Network, hashes::Hash};
    +        use $crate::chain::{ConfirmationTime, BlockId};
    +        use $crate::wallet::{AddressIndex, Wallet};
    +        let descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/0/*)";
    +        let change_descriptor = "tr([73c5da0a/86'/0'/0']tprv8fMn4hSKPRC1oaCPqxDb1JWtgkpeiQvZhsr8W2xuy3GEMkzoArcAWTfJxYb6Wj8XNNDWEjfYKK4wGQXh3ZUXhDF2NcnsALpWTeSwarJt7Vc/1/*)";
    +
    +        let mut wallet = Wallet::new_no_persist(
    +            descriptor,
    +            Some(change_descriptor),
                 Network::Regtest,
    -            AnyDatabase::Memory(MemoryDatabase::new()),
             )
             .unwrap();
    -
    -        let tx_meta = testutils! {
    -                @tx ( (@external descriptors, 0) => 50_000 )
    -        };
    -
    -        // Add the transaction to our db, but do not sync the db.
    -        crate::populate_test_db!(wallet.database.borrow_mut(), tx_meta, None);
    -
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        // Since we never synced the wallet we don't have a last_sync_height
    -        // we could use to try to prevent fee sniping. We default to 0.
    -        assert_eq!(psbt.unsigned_tx.lock_time, PackedLockTime(0));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_fee_sniping_locktime_provided_height() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let sync_time = SyncTime {
    -            block_time: BlockTime {
    -                height: 24,
    -                timestamp: 0,
    -            },
    +        let address = wallet.get_address(AddressIndex::New).address;
    +        let tx = Transaction {
    +            version: 1,
    +            lock_time: PackedLockTime(0),
    +            input: vec![],
    +            output: vec![TxOut {
    +                value: 500_000,
    +                script_pubkey: address.script_pubkey(),
    +            }],
             };
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_sync_time(sync_time)
    -            .unwrap();
    -        let current_height = 25;
    -        builder.current_height(current_height);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        // current_height will override the last sync height
    -        assert_eq!(psbt.unsigned_tx.lock_time, PackedLockTime(current_height));
    -    }
    +        let _ = wallet.insert_checkpoint(BlockId { height: 1_000, hash: BlockHash::all_zeros() });
    +        let _ = wallet.insert_tx(tx.clone(), ConfirmationTime::Confirmed {
    +            height: 500,
    +            time: 50_000
    +        });
     
    -    #[test]
    -    fn test_create_tx_fee_sniping_locktime_last_sync() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let sync_time = SyncTime {
    -            block_time: BlockTime {
    -                height: 25,
    -                timestamp: 0,
    -            },
    -        };
             wallet
    -            .database
    -            .borrow_mut()
    -            .set_sync_time(sync_time.clone())
    -            .unwrap();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        // If there's no current_height we're left with using the last sync height
    -        assert_eq!(
    -            psbt.unsigned_tx.lock_time,
    -            PackedLockTime(sync_time.block_time.height)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.lock_time, PackedLockTime(100_000));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .current_height(630_001)
    -            .nlocktime(LockTime::from_height(630_000).unwrap());
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        // When we explicitly specify a nlocktime
    -        // we don't try any fee sniping prevention trick
    -        // (we ignore the current_height)
    -        assert_eq!(psbt.unsigned_tx.lock_time, PackedLockTime(630_000));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime_compatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .nlocktime(LockTime::from_height(630_000).unwrap());
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.lock_time, PackedLockTime(630_000));
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested timelock of `Blocks(Height(50000))`, but at least `Blocks(Height(100000))` is required to spend from this script"
    -    )]
    -    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .nlocktime(LockTime::from_height(50000).unwrap());
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(6));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_with_default_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, _) = builder.finish().unwrap();
    -        // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
    -        // It will be set to the OP_CSV value, in this case 6
    -        assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(6));
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "Cannot enable RBF with nSequence `Sequence(3)` given a required OP_CSV of `Sequence(6)`"
    -    )]
    -    fn test_create_tx_with_custom_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf_with_sequence(Sequence(3));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFE));
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
    -    fn test_create_tx_invalid_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf_with_sequence(Sequence(0xFFFFFFFE));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf_with_sequence(Sequence(0xDEADBEEF));
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xDEADBEEF));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sequence() {
    -        let descriptors = testutils!(@descriptors (get_test_wpkh()));
    -        let wallet = Wallet::new(
    -            &descriptors.0,
    -            None,
    -            Network::Regtest,
    -            AnyDatabase::Memory(MemoryDatabase::new()),
    -        )
    -        .unwrap();
    -
    -        let tx_meta = testutils! {
    -                @tx ( (@external descriptors, 0) => 50_000 )
    -        };
    -
    -        // Add the transaction to our db, but do not sync the db. Unsynced db
    -        // should trigger the default sequence value for a new transaction as 0xFFFFFFFF
    -        crate::populate_test_db!(wallet.database.borrow_mut(), tx_meta, None);
    -
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFF));
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
    -    )]
    -    fn test_create_tx_change_policy_no_internal() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .do_not_spend_change();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_drain_wallet_and_drain_to() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.unsigned_tx.output[0].value,
    -            50_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -        let drain_addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 20_000)
    -            .drain_to(drain_addr.script_pubkey())
    -            .drain_wallet();
    -        let (psbt, details) = builder.finish().unwrap();
    -        let outputs = psbt.unsigned_tx.output;
    -
    -        assert_eq!(outputs.len(), 2);
    -        let main_output = outputs
    -            .iter()
    -            .find(|x| x.script_pubkey == addr.script_pubkey())
    -            .unwrap();
    -        let drain_output = outputs
    -            .iter()
    -            .find(|x| x.script_pubkey == drain_addr.script_pubkey())
    -            .unwrap();
    -        assert_eq!(main_output.value, 20_000,);
    -        assert_eq!(drain_output.value, 30_000 - details.fee.unwrap_or(0));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_drain_to_and_utxos() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let utxos: Vec<_> = wallet
    -            .get_available_utxos()
    -            .unwrap()
    -            .into_iter()
    -            .map(|(u, _)| u.outpoint)
    -            .collect();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .add_utxos(&utxos)
    -            .unwrap();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.unsigned_tx.output[0].value,
    -            50_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoRecipients")]
    -    fn test_create_tx_drain_to_no_drain_wallet_no_utxos() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let drain_addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(drain_addr.script_pubkey());
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::default(), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_absolute_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_absolute(100);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.fee.unwrap_or(0), 100);
    -        assert_eq!(psbt.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.unsigned_tx.output[0].value,
    -            50_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_absolute_zero_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_absolute(0);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.fee.unwrap_or(0), 0);
    -        assert_eq!(psbt.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.unsigned_tx.output[0].value,
    -            50_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_absolute_high_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_absolute(60_000);
    -        let (_psbt, _details) = builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_add_change() {
    -        use super::tx_builder::TxOrdering;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .ordering(TxOrdering::Untouched);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.output.len(), 2);
    -        assert_eq!(psbt.unsigned_tx.output[0].value, 25_000);
    -        assert_eq!(
    -            psbt.unsigned_tx.output[1].value,
    -            25_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_skip_change_dust() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 49_800);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.output.len(), 1);
    -        assert_eq!(psbt.unsigned_tx.output[0].value, 49_800);
    -        assert_eq!(details.fee.unwrap_or(0), 200);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_drain_to_dust_amount() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        // very high fee rate, so that the only output would be below dust
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_rate(FeeRate::from_sat_per_vb(453.0));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_ordering_respected() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .add_recipient(addr.script_pubkey(), 10_000)
    -            .ordering(super::tx_builder::TxOrdering::Bip69Lexicographic);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.output.len(), 3);
    -        assert_eq!(
    -            psbt.unsigned_tx.output[0].value,
    -            10_000 - details.fee.unwrap_or(0)
    -        );
    -        assert_eq!(psbt.unsigned_tx.output[1].value, 10_000);
    -        assert_eq!(psbt.unsigned_tx.output[2].value, 30_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 30_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.inputs[0].sighash_type, None);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .sighash(bitcoin::EcdsaSighashType::Single.into());
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].sighash_type,
    -            Some(bitcoin::EcdsaSighashType::Single.into())
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_input_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.inputs[0].bip32_derivation.len(), 1);
    -        assert_eq!(
    -            psbt.inputs[0].bip32_derivation.values().next().unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_output_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
    -        // cache some addresses
    -        wallet.get_address(New).unwrap();
    -
    -        let addr = testutils!(@external descriptors, 5);
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.outputs[0].bip32_derivation.len(), 1);
    -        assert_eq!(
    -            psbt.outputs[0].bip32_derivation.values().next().unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_script_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].redeem_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -        assert_eq!(psbt.inputs[0].witness_script, None);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_witness_script_p2wsh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, None);
    -        assert_eq!(
    -            psbt.inputs[0].witness_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex(
    -                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
    -            )
    -            .unwrap(),
    -        );
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
    -        assert_eq!(psbt.inputs[0].witness_script, Some(script));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_non_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_none());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_only_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .only_witness_utxo()
    -            .drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_none());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_shwpkh_has_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_both_non_witness_utxo_and_witness_utxo_default() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_add_utxo() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let small_output_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .add_utxo(OutPoint {
    -                txid: small_output_txid,
    -                vout: 0,
    -            })
    -            .unwrap();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.unsigned_tx.input.len(),
    -            2,
    -            "should add an additional input since 25_000 < 30_000"
    -        );
    -        assert_eq!(details.sent, 75_000, "total should be sum of both inputs");
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_manually_selected_insufficient() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let small_output_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .add_utxo(OutPoint {
    -                txid: small_output_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .manually_selected_only();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "SpendingPolicyRequired(External)")]
    -    fn test_create_tx_policy_path_required() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 30_000);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_policy_path_no_csv() {
    -        let descriptors = testutils!(@descriptors (get_test_wpkh()));
    -        let wallet = Wallet::new(
    -            &descriptors.0,
    -            None,
    -            Network::Regtest,
    -            AnyDatabase::Memory(MemoryDatabase::new()),
    -        )
    -        .unwrap();
    -
    -        let tx_meta = testutils! {
    -                @tx ( (@external descriptors, 0) => 50_000 )
    -        };
    -
    -        // Add the transaction to our db, but do not sync the db. Unsynced db
    -        // should trigger the default sequence value for a new transaction as 0xFFFFFFFF
    -        crate::populate_test_db!(wallet.database.borrow_mut(), tx_meta, None);
    -
    -        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
    -        let root_id = external_policy.id;
    -        // child #0 is just the key "A"
    -        let path = vec![(root_id, vec![0])].into_iter().collect();
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .policy_path(path, KeychainKind::External);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(0xFFFFFFFF));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_policy_path_use_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
    -        let root_id = external_policy.id;
    -        // child #1 is or(pk(B),older(144))
    -        let path = vec![(root_id, vec![1])].into_iter().collect();
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .policy_path(path, KeychainKind::External);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.unsigned_tx.input[0].sequence, Sequence(144));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_global_xpubs_with_origin() {
    -        use bitcoin::hashes::hex::FromHex;
    -        use bitcoin::util::bip32;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .add_global_xpubs();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        let key = bip32::ExtendedPubKey::from_str("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
    -        let fingerprint = bip32::Fingerprint::from_hex("73756c7f").unwrap();
    -        let path = bip32::DerivationPath::from_str("m/48'/0'/0'/2'").unwrap();
    -
    -        assert_eq!(psbt.xpub.len(), 1);
    -        assert_eq!(psbt.xpub.get(&key), Some(&(fingerprint, path)));
    -    }
    -
    -    #[test]
    -    fn test_add_foreign_utxo() {
    -        let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
    -        let (wallet2, _, _) =
    -            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let utxo = wallet2.list_unspent().unwrap().remove(0);
    -        let foreign_utxo_satisfaction = wallet2
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -
    -        let psbt_input = psbt::Input {
    -            witness_utxo: Some(utxo.txout.clone()),
    -            ..Default::default()
    -        };
    -
    -        let mut builder = wallet1.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 60_000)
    -            .only_witness_utxo()
    -            .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
    -            .unwrap();
    -        let (mut psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            details.sent - details.received,
    -            10_000 + details.fee.unwrap_or(0),
    -            "we should have only net spent ~10_000"
    -        );
    -
    -        assert!(
    -            psbt.unsigned_tx
    -                .input
    -                .iter()
    -                .any(|input| input.previous_output == utxo.outpoint),
    -            "foreign_utxo should be in there"
    -        );
    -
    -        let finished = wallet1
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    trust_witness_utxo: true,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -
    -        assert!(
    -            !finished,
    -            "only one of the inputs should have been signed so far"
    -        );
    -
    -        let finished = wallet2
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    trust_witness_utxo: true,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -        assert!(finished, "all the inputs should have been signed now");
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Generic(\"Foreign utxo missing witness_utxo or non_witness_utxo\")")]
    -    fn test_add_foreign_utxo_invalid_psbt_input() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let mut builder = wallet.build_tx();
    -        let outpoint = wallet.list_unspent().unwrap()[0].outpoint;
    -        let foreign_utxo_satisfaction = wallet
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -        builder
    -            .add_foreign_utxo(outpoint, psbt::Input::default(), foreign_utxo_satisfaction)
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_add_foreign_utxo_where_outpoint_doesnt_match_psbt_input() {
    -        let (wallet1, _, txid1) = get_funded_wallet(get_test_wpkh());
    -        let (wallet2, _, txid2) =
    -            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
    -
    -        let utxo2 = wallet2.list_unspent().unwrap().remove(0);
    -        let tx1 = wallet1
    -            .database
    -            .borrow()
    -            .get_tx(&txid1, true)
    -            .unwrap()
    -            .unwrap()
    -            .transaction
    -            .unwrap();
    -        let tx2 = wallet2
    -            .database
    -            .borrow()
    -            .get_tx(&txid2, true)
    -            .unwrap()
    -            .unwrap()
    -            .transaction
    -            .unwrap();
    -
    -        let satisfaction_weight = wallet2
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -
    -        let mut builder = wallet1.build_tx();
    -        assert!(
    -            builder
    -                .add_foreign_utxo(
    -                    utxo2.outpoint,
    -                    psbt::Input {
    -                        non_witness_utxo: Some(tx1),
    -                        ..Default::default()
    -                    },
    -                    satisfaction_weight
    -                )
    -                .is_err(),
    -            "should fail when outpoint doesn't match psbt_input"
    -        );
    -        assert!(
    -            builder
    -                .add_foreign_utxo(
    -                    utxo2.outpoint,
    -                    psbt::Input {
    -                        non_witness_utxo: Some(tx2),
    -                        ..Default::default()
    -                    },
    -                    satisfaction_weight
    -                )
    -                .is_ok(),
    -            "shoulld be ok when outpoint does match psbt_input"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_add_foreign_utxo_only_witness_utxo() {
    -        let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
    -        let (wallet2, _, txid2) =
    -            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let utxo2 = wallet2.list_unspent().unwrap().remove(0);
    -
    -        let satisfaction_weight = wallet2
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -
    -        let mut builder = wallet1.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 60_000);
    -
    -        {
    -            let mut builder = builder.clone();
    -            let psbt_input = psbt::Input {
    -                witness_utxo: Some(utxo2.txout.clone()),
    -                ..Default::default()
    -            };
    -            builder
    -                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
    -                .unwrap();
    -            assert!(
    -                builder.finish().is_err(),
    -                "psbt_input with witness_utxo should fail with only witness_utxo"
    -            );
    -        }
    -
    -        {
    -            let mut builder = builder.clone();
    -            let psbt_input = psbt::Input {
    -                witness_utxo: Some(utxo2.txout.clone()),
    -                ..Default::default()
    -            };
    -            builder
    -                .only_witness_utxo()
    -                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
    -                .unwrap();
    -            assert!(
    -                builder.finish().is_ok(),
    -                "psbt_input with just witness_utxo should succeed when `only_witness_utxo` is enabled"
    -            );
    -        }
    -
    -        {
    -            let mut builder = builder.clone();
    -            let tx2 = wallet2
    -                .database
    -                .borrow()
    -                .get_tx(&txid2, true)
    -                .unwrap()
    -                .unwrap()
    -                .transaction
    -                .unwrap();
    -            let psbt_input = psbt::Input {
    -                non_witness_utxo: Some(tx2),
    -                ..Default::default()
    -            };
    -            builder
    -                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
    -                .unwrap();
    -            assert!(
    -                builder.finish().is_ok(),
    -                "psbt_input with non_witness_utxo should succeed by default"
    -            );
    -        }
    -    }
    -
    -    #[test]
    -    fn test_get_psbt_input() {
    -        // this should grab a known good utxo and set the input
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        for utxo in wallet.list_unspent().unwrap() {
    -            let psbt_input = wallet.get_psbt_input(utxo, None, false).unwrap();
    -            assert!(psbt_input.witness_utxo.is_some() || psbt_input.non_witness_utxo.is_some());
    -        }
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "MissingKeyOrigin(\"tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3\")"
    -    )]
    -    fn test_create_tx_global_xpubs_origin_missing() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .add_global_xpubs();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_global_xpubs_master_without_origin() {
    -        use bitcoin::hashes::hex::FromHex;
    -        use bitcoin::util::bip32;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .add_global_xpubs();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        let key = bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
    -        let fingerprint = bip32::Fingerprint::from_hex("997a323b").unwrap();
    -
    -        assert_eq!(psbt.xpub.len(), 1);
    -        assert_eq!(
    -            psbt.xpub.get(&key),
    -            Some(&(fingerprint, bip32::DerivationPath::default()))
    -        );
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "IrreplaceableTransaction")]
    -    fn test_bump_fee_irreplaceable_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.build_fee_bump(txid).unwrap().finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "TransactionConfirmed")]
    -    fn test_bump_fee_confirmed_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        details.confirmation_time = Some(BlockTime {
    -            timestamp: 12345678,
    -            height: 42,
    -        });
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.build_fee_bump(txid).unwrap().finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeRateTooLow")]
    -    fn test_bump_fee_low_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(1.0));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeTooLow")]
    -    fn test_bump_fee_low_abs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(10);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeTooLow")]
    -    fn test_bump_fee_zero_abs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(0);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_change() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(2.5)).enable_rbf();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert_eq!(
    -            details.received + details.fee.unwrap_or(0),
    -            original_details.received + original_details.fee.unwrap_or(0)
    -        );
    -        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            25_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_reduce_change() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(200);
    -        builder.enable_rbf();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert_eq!(
    -            details.received + details.fee.unwrap_or(0),
    -            original_details.received + original_details.fee.unwrap_or(0)
    -        );
    -        assert!(
    -            details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0),
    -            "{} > {}",
    -            details.fee.unwrap_or(0),
    -            original_details.fee.unwrap_or(0)
    -        );
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            25_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fee.unwrap_or(0), 200);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_single_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .fee_rate(FeeRate::from_sat_per_vb(2.5))
    -            .allow_shrinking(addr.script_pubkey())
    -            .unwrap();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_reduce_single_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .allow_shrinking(addr.script_pubkey())
    -            .unwrap()
    -            .fee_absolute(300);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
    -
    -        assert_eq!(details.fee.unwrap_or(0), 300);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_drain_wallet() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        // receive an extra tx so that our wallet has two utxos.
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -        let outpoint = OutPoint {
    -            txid: incoming_txid,
    -            vout: 0,
    -        };
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .add_utxo(outpoint)
    -            .unwrap()
    -            .manually_selected_only()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -        assert_eq!(original_details.sent, 25_000);
    -
    -        // for the new feerate, it should be enough to reduce the output, but since we specify
    -        // `drain_wallet` we expect to spend everything
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .drain_wallet()
    -            .allow_shrinking(addr.script_pubkey())
    -            .unwrap()
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        let (_, details) = builder.finish().unwrap();
    -        assert_eq!(details.sent, 75_000);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bump_fee_remove_output_manually_selected_only() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        // receive an extra tx so that our wallet has two utxos. then we manually pick only one of
    -        // them, and make sure that `bump_fee` doesn't try to add more. This fails because we've
    -        // told the wallet it's not allowed to add more inputs AND it can't reduce the value of the
    -        // existing output. In other words, bump_fee + manually_selected_only is always an error
    -        // unless you've also set "allow_shrinking" OR there is a change output.
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -        let outpoint = OutPoint {
    -            txid: incoming_txid,
    -            vout: 0,
    -        };
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .add_utxo(outpoint)
    -            .unwrap()
    -            .manually_selected_only()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -        assert_eq!(original_details.sent, 25_000);
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .manually_selected_only()
    -            .fee_rate(FeeRate::from_sat_per_vb(255.0));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(6_000);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fee.unwrap_or(0), 6_000);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_no_change_add_input_and_change() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        // initially make a tx without change by using `drain_to`
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .add_utxo(OutPoint {
    -                txid: incoming_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .manually_selected_only()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // now bump the fees without using `allow_shrinking`. the wallet should add an
    -        // extra input and a change output, and leave the original output untouched
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        let original_send_all_amount = original_details.sent - original_details.fee.unwrap_or(0);
    -        assert_eq!(details.sent, original_details.sent + 50_000);
    -        assert_eq!(
    -            details.received,
    -            75_000 - original_send_all_amount - details.fee.unwrap_or(0)
    -        );
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            original_send_all_amount
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            75_000 - original_send_all_amount - details.fee.unwrap_or(0)
    -        );
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input_change_dust() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        assert_eq!(tx.input.len(), 1);
    -        assert_eq!(tx.output.len(), 2);
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        let original_tx_weight = tx.weight();
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        // We set a fee high enough that during rbf we are forced to add
    -        // a new input and also that we have to remove the change
    -        // that we had previously
    -
    -        // We calculate the new weight as:
    -        //   original weight
    -        // + extra input weight: 160 WU = (32 (prevout) + 4 (vout) + 4 (nsequence)) * 4
    -        // + input satisfaction weight: 112 WU = 106 (witness) + 2 (witness len) + (1 (script len)) * 4
    -        // - change output weight: 124 WU = (8 (value) + 1 (script len) + 22 (script)) * 4
    -        let new_tx_weight = original_tx_weight + 160 + 112 - 124;
    -        // two inputs (50k, 25k) and one output (45k) - epsilon
    -        // We use epsilon here to avoid asking for a slightly too high feerate
    -        let fee_abs = 50_000 + 25_000 - 45_000 - 10;
    -        builder.fee_rate(FeeRate::from_wu(fee_abs, new_tx_weight));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            original_details.received,
    -            5_000 - original_details.fee.unwrap_or(0)
    -        );
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0), 30_000);
    -        assert_eq!(details.received, 0);
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_force_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // the new fee_rate is low enough that just reducing the change would be fine, but we force
    -        // the addition of an extra input with `add_utxo()`
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .add_utxo(OutPoint {
    -                txid: incoming_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_force_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // the new fee_rate is low enough that just reducing the change would be fine, but we force
    -        // the addition of an extra input with `add_utxo()`
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .add_utxo(OutPoint {
    -                txid: incoming_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .fee_absolute(250);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fee.unwrap_or(0), 250);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bump_fee_unconfirmed_inputs_only() {
    -        // We try to bump the fee, but:
    -        // - We can't reduce the change, as we have no change
    -        // - All our UTXOs are unconfirmed
    -        // So, we fail with "InsufficientFunds", as per RBF rule 2:
    -        // The replacement transaction may only include an unconfirmed input
    -        // if that input was included in one of the original transactions.
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_wallet()
    -            .drain_to(addr.script_pubkey())
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        // Now we receive one transaction with 0 confirmations. We won't be able to use that for
    -        // fee bumping, as it's still unconfirmed!
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 0)),
    -            Some(100),
    -        );
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(25.0));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_unconfirmed_input() {
    -        // We create a tx draining the wallet and spending one confirmed
    -        // and one unconfirmed UTXO. We check that we can fee bump normally
    -        // (BIP125 rule 2 only apply to newly added unconfirmed input, you can
    -        // always fee bump with an unconfirmed input if it was included in the
    -        // original transaction)
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        // We receive a tx with 0 confirmations, which will be used as an input
    -        // in the drain tx.
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 0)),
    -            Some(100),
    -        );
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_wallet()
    -            .drain_to(addr.script_pubkey())
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .fee_rate(FeeRate::from_sat_per_vb(15.0))
    -            .allow_shrinking(addr.script_pubkey())
    -            .unwrap();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_fee_amount_negative_drain_val() {
    -        // While building the transaction, bdk would calculate the drain_value
    -        // as
    -        // current_delta - fee_amount - drain_fee
    -        // using saturating_sub, meaning that if the result would end up negative,
    -        // it'll remain to zero instead.
    -        // This caused a bug in master where we would calculate the wrong fee
    -        // for a transaction.
    -        // See https://github.com/bitcoindevkit/bdk/issues/660
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt").unwrap();
    -        let fee_rate = FeeRate::from_sat_per_vb(2.01);
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 8859 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(send_to.script_pubkey(), 8630)
    -            .add_utxo(OutPoint::new(incoming_txid, 0))
    -            .unwrap()
    -            .enable_rbf()
    -            .fee_rate(fee_rate);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs.len() == 1);
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate, @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_with_master_fingerprint_and_path() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_bip44_path() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_sh_wpkh() {
    -        let (wallet, _, _) = get_funded_wallet("sh(wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_wif() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_no_hd_keypaths() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        psbt.inputs[0].bip32_derivation.clear();
    -        assert_eq!(psbt.inputs[0].bip32_derivation.len(), 0);
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_include_output_redeem_witness_script() {
    -        let (wallet, _, _) = get_funded_wallet("sh(wsh(multi(1,cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW,cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu)))");
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .include_output_redeem_witness_script();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        // p2sh-p2wsh transaction should contain both witness and redeem scripts
    -        assert!(psbt
    -            .outputs
    -            .iter()
    -            .any(|output| output.redeem_script.is_some() && output.witness_script.is_some()));
    -    }
    -
    -    #[test]
    -    fn test_signing_only_one_of_multiple_inputs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .include_output_redeem_witness_script();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        // add another input to the psbt that is at least passable.
    -        let dud_input = bitcoin::util::psbt::Input {
    -            witness_utxo: Some(TxOut {
    -                value: 100_000,
    -                script_pubkey: miniscript::Descriptor::<bitcoin::PublicKey>::from_str(
    -                    "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
    -                )
    -                .unwrap()
    -                .script_pubkey(),
    -            }),
    -            ..Default::default()
    -        };
    -
    -        psbt.inputs.push(dud_input);
    -        psbt.unsigned_tx.input.push(bitcoin::TxIn::default());
    -        let is_final = wallet
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    trust_witness_utxo: true,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -        assert!(
    -            !is_final,
    -            "shouldn't be final since we can't sign one of the inputs"
    -        );
    -        assert!(
    -            psbt.inputs[0].final_script_witness.is_some(),
    -            "should finalized input it signed"
    -        )
    -    }
    -
    -    #[test]
    -    fn test_remove_partial_sigs_after_finalize_sign_option() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -
    -        for remove_partial_sigs in &[true, false] {
    -            let addr = wallet.get_address(New).unwrap();
    -            let mut builder = wallet.build_tx();
    -            builder.drain_to(addr.script_pubkey()).drain_wallet();
    -            let mut psbt = builder.finish().unwrap().0;
    -
    -            assert!(wallet
    -                .sign(
    -                    &mut psbt,
    -                    SignOptions {
    -                        remove_partial_sigs: *remove_partial_sigs,
    -                        ..Default::default()
    -                    },
    -                )
    -                .unwrap());
    -
    -            psbt.inputs.iter().for_each(|input| {
    -                if *remove_partial_sigs {
    -                    assert!(input.partial_sigs.is_empty())
    -                } else {
    -                    assert!(!input.partial_sigs.is_empty())
    -                }
    -            });
    -        }
    -    }
    -
    -    #[test]
    -    fn test_try_finalize_sign_option() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -
    -        for try_finalize in &[true, false] {
    -            let addr = wallet.get_address(New).unwrap();
    -            let mut builder = wallet.build_tx();
    -            builder.drain_to(addr.script_pubkey()).drain_wallet();
    -            let mut psbt = builder.finish().unwrap().0;
    -
    -            let finalized = wallet
    -                .sign(
    -                    &mut psbt,
    -                    SignOptions {
    -                        try_finalize: *try_finalize,
    -                        ..Default::default()
    -                    },
    -                )
    -                .unwrap();
    -
    -            psbt.inputs.iter().for_each(|input| {
    -                if *try_finalize {
    -                    assert!(finalized);
    -                    assert!(input.final_script_sig.is_some());
    -                    assert!(input.final_script_witness.is_some());
    -                } else {
    -                    assert!(!finalized);
    -                    assert!(input.final_script_sig.is_none());
    -                    assert!(input.final_script_witness.is_none());
    -                }
    -            });
    -        }
    -    }
    -
    -    #[test]
    -    fn test_sign_nonstandard_sighash() {
    -        let sighash = EcdsaSighashType::NonePlusAnyoneCanPay;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .sighash(sighash.into())
    -            .drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let result = wallet.sign(&mut psbt, Default::default());
    -        assert!(
    -            result.is_err(),
    -            "Signing should have failed because the TX uses non-standard sighashes"
    -        );
    -        assert_matches!(
    -            result,
    -            Err(Error::Signer(SignerError::NonStandardSighash)),
    -            "Signing failed with the wrong error type"
    -        );
    -
    -        // try again after opting-in
    -        let result = wallet.sign(
    -            &mut psbt,
    -            SignOptions {
    -                allow_all_sighashes: true,
    -                ..Default::default()
    -            },
    -        );
    -        assert!(result.is_ok(), "Signing should have worked");
    -        assert!(
    -            result.unwrap(),
    -            "Should finalize the input since we can produce signatures"
    -        );
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(
    -            *extracted.input[0].witness.to_vec()[0].last().unwrap(),
    -            sighash.to_u32() as u8,
    -            "The signature should have been made with the right sighash"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_unused_address() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_next_unused_address() {
    -        let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)";
    -        let descriptors = testutils!(@descriptors (descriptor));
    -        let wallet = Wallet::new(
    -            &descriptors.0,
    -            None,
    -            Network::Testnet,
    -            MemoryDatabase::new(),
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        // use the above address
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_peek_address_at_index() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(1)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(0)).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(2)).unwrap().to_string(),
    -            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
    -        );
    -
    -        // current new address is not affected
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_peek_address_at_index_not_derivable() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/1)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(1)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(0)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(2)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_reset_address_index() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        // new index 0
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        // new index 1
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        // new index 2
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
    -        );
    -
    -        //  reset index 1 again
    -        assert_eq!(
    -            wallet.get_address(Reset(1)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        // new index 2 again
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_returns_index_and_address() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        // new index 0
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 0,
    -                address: Address::from_str("tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a").unwrap(),
    -                keychain: KeychainKind::External,
    -            }
    -        );
    -
    -        // new index 1
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 1,
    -                address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap(),
    -                keychain: KeychainKind::External,
    -            }
    -        );
    -
    -        // peek index 25
    -        assert_eq!(
    -            wallet.get_address(Peek(25)).unwrap(),
    -            AddressInfo {
    -                index: 25,
    -                address: Address::from_str("tb1qsp7qu0knx3sl6536dzs0703u2w2ag6ppl9d0c2").unwrap(),
    -                keychain: KeychainKind::External,
    -            }
    -        );
    -
    -        // new index 2
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 2,
    -                address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap(),
    -                keychain: KeychainKind::External,
    -            }
    -        );
    -
    -        //  reset index 1 again
    -        assert_eq!(
    -            wallet.get_address(Reset(1)).unwrap(),
    -            AddressInfo {
    -                index: 1,
    -                address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap(),
    -                keychain: KeychainKind::External,
    -            }
    -        );
    -
    -        // new index 2 again
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 2,
    -                address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap(),
    -                keychain: KeychainKind::External,
    -            }
    -        );
    -    }
    -
    -    #[test]
    -    fn test_sending_to_bip350_bech32m_address() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr =
    -            Address::from_str("tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c")
    -                .unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 45_000);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_get_address() {
    -        use crate::descriptor::template::Bip84;
    -        let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        let wallet = Wallet::new(
    -            Bip84(key, KeychainKind::External),
    -            Some(Bip84(key, KeychainKind::Internal)),
    -            Network::Regtest,
    -            MemoryDatabase::default(),
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(AddressIndex::New).unwrap(),
    -            AddressInfo {
    -                index: 0,
    -                address: Address::from_str("bcrt1qrhgaqu0zvf5q2d0gwwz04w0dh0cuehhqvzpp4w").unwrap(),
    -                keychain: KeychainKind::External,
    -            }
    -        );
    -
    -        assert_eq!(
    -            wallet.get_internal_address(AddressIndex::New).unwrap(),
    -            AddressInfo {
    -                index: 0,
    -                address: Address::from_str("bcrt1q0ue3s5y935tw7v3gmnh36c5zzsaw4n9c9smq79").unwrap(),
    -                keychain: KeychainKind::Internal,
    -            }
    -        );
    -
    -        let wallet = Wallet::new(
    -            Bip84(key, KeychainKind::External),
    -            None,
    -            Network::Regtest,
    -            MemoryDatabase::default(),
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_internal_address(AddressIndex::New).unwrap(),
    -            AddressInfo {
    -                index: 0,
    -                address: Address::from_str("bcrt1qrhgaqu0zvf5q2d0gwwz04w0dh0cuehhqvzpp4w").unwrap(),
    -                keychain: KeychainKind::Internal,
    -            },
    -            "when there's no internal descriptor it should just use external"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_get_address_no_reuse_single_descriptor() {
    -        use crate::descriptor::template::Bip84;
    -        use std::collections::HashSet;
    -
    -        let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        let wallet = Wallet::new(
    -            Bip84(key, KeychainKind::External),
    -            None,
    -            Network::Regtest,
    -            MemoryDatabase::default(),
    -        )
    -        .unwrap();
    -
    -        let mut used_set = HashSet::new();
    -
    -        (0..3).for_each(|_| {
    -            let external_addr = wallet.get_address(AddressIndex::New).unwrap().address;
    -            assert!(used_set.insert(external_addr));
    -
    -            let internal_addr = wallet
    -                .get_internal_address(AddressIndex::New)
    -                .unwrap()
    -                .address;
    -            assert!(used_set.insert(internal_addr));
    -        });
    -    }
    -
    -    #[test]
    -    fn test_taproot_psbt_populate_tap_key_origins() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0]
    -                .tap_key_origins
    -                .clone()
    -                .into_iter()
    -                .collect::<Vec<_>>(),
    -            vec![(
    -                from_str!("b96d3a3dc76a4fc74e976511b23aecb78e0754c23c0ed7a6513e18cbbc7178e9"),
    -                (vec![], (from_str!("f6a5cb8b"), from_str!("m/0")))
    -            )],
    -            "Wrong input tap_key_origins"
    -        );
    -        assert_eq!(
    -            psbt.outputs[0]
    -                .tap_key_origins
    -                .clone()
    -                .into_iter()
    -                .collect::<Vec<_>>(),
    -            vec![(
    -                from_str!("e9b03068cf4a2621d4f81e68f6c4216e6bd260fe6edf6acc55c8d8ae5aeff0a8"),
    -                (vec![], (from_str!("f6a5cb8b"), from_str!("m/1")))
    -            )],
    -            "Wrong output tap_key_origins"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_taproot_psbt_populate_tap_key_origins_repeated_key() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_repeated_key());
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let path = vec![("e5mmg3xh".to_string(), vec![0])]
    -            .into_iter()
    -            .collect();
    -
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .policy_path(path, KeychainKind::External);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        let mut input_key_origins = psbt.inputs[0]
    -            .tap_key_origins
    -            .clone()
    -            .into_iter()
    -            .collect::<Vec<_>>();
    -        input_key_origins.sort();
    -
    -        assert_eq!(
    -            input_key_origins,
    -            vec![
    -                (
    -                    from_str!("b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55"),
    -                    (
    -                        vec![],
    -                        (FromStr::from_str("871fd295").unwrap(), vec![].into())
    -                    )
    -                ),
    -                (
    -                    from_str!("2b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3"),
    -                    (
    -                        vec![
    -                            from_str!(
    -                                "858ad7a7d7f270e2c490c4d6ba00c499e46b18fdd59ea3c2c47d20347110271e"
    -                            ),
    -                            from_str!(
    -                                "f6e927ad4492c051fe325894a4f5f14538333b55a35f099876be42009ec8f903"
    -                            ),
    -                        ],
    -                        (FromStr::from_str("ece52657").unwrap(), vec![].into())
    -                    )
    -                )
    -            ],
    -            "Wrong input tap_key_origins"
    -        );
    -
    -        let mut output_key_origins = psbt.outputs[0]
    -            .tap_key_origins
    -            .clone()
    -            .into_iter()
    -            .collect::<Vec<_>>();
    -        output_key_origins.sort();
    -
    -        assert_eq!(
    -            input_key_origins, output_key_origins,
    -            "Wrong output tap_key_origins"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_taproot_psbt_input_tap_tree() {
    -        use crate::bitcoin::psbt::serialize::Deserialize;
    -        use crate::bitcoin::psbt::TapTree;
    -        use bitcoin::hashes::hex::FromHex;
    -        use bitcoin::util::taproot;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree());
    -        let addr = wallet.get_address(AddressIndex::Peek(0)).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].tap_merkle_root,
    -            Some(
    -                FromHex::from_hex(
    -                    "61f81509635053e52d9d1217545916167394490da2287aca4693606e43851986"
    -                )
    -                .unwrap()
    -            ),
    -        );
    -        assert_eq!(
    -            psbt.inputs[0].tap_scripts.clone().into_iter().collect::<Vec<_>>(),
    -            vec![
    -                (taproot::ControlBlock::from_slice(&Vec::<u8>::from_hex("c0b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55b7ef769a745e625ed4b9a4982a4dc08274c59187e73e6f07171108f455081cb2").unwrap()).unwrap(), (from_str!("208aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642ac"), taproot::LeafVersion::TapScript)),
    -                (taproot::ControlBlock::from_slice(&Vec::<u8>::from_hex("c0b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55b9a515f7be31a70186e3c5937ee4a70cc4b4e1efe876c1d38e408222ffc64834").unwrap()).unwrap(), (from_str!("2051494dc22e24a32fe9dcfbd7e85faf345fa1df296fb49d156e859ef345201295ac"), taproot::LeafVersion::TapScript)),
    -            ],
    -        );
    -        assert_eq!(
    -            psbt.inputs[0].tap_internal_key,
    -            Some(from_str!(
    -                "b511bd5771e47ee27558b1765e87b541668304ec567721c7b880edc0a010da55"
    -            ))
    -        );
    -
    -        // Since we are creating an output to the same address as the input, assert that the
    -        // internal_key is the same
    -        assert_eq!(
    -            psbt.inputs[0].tap_internal_key,
    -            psbt.outputs[0].tap_internal_key
    -        );
    -
    -        assert_eq!(
    -            psbt.outputs[0].tap_tree,
    -            Some(TapTree::deserialize(&Vec::<u8>::from_hex("01c022208aee2b8120a5f157f1223f72b5e62b825831a27a9fdf427db7cc697494d4a642ac01c0222051494dc22e24a32fe9dcfbd7e85faf345fa1df296fb49d156e859ef345201295ac",).unwrap()).unwrap())
    -        );
    -    }
    -
    -    #[test]
    -    fn test_taproot_sign_missing_witness_utxo() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        let witness_utxo = psbt.inputs[0].witness_utxo.take();
    -
    -        let result = wallet.sign(
    -            &mut psbt,
    -            SignOptions {
    -                allow_all_sighashes: true,
    -                ..Default::default()
    -            },
    -        );
    -        assert_matches!(
    -            result,
    -            Err(Error::Signer(SignerError::MissingWitnessUtxo)),
    -            "Signing should have failed with the correct error because the witness_utxo is missing"
    -        );
    -
    -        // restore the witness_utxo
    -        psbt.inputs[0].witness_utxo = witness_utxo;
    -
    -        let result = wallet.sign(
    -            &mut psbt,
    -            SignOptions {
    -                allow_all_sighashes: true,
    -                ..Default::default()
    -            },
    -        );
    -
    -        assert_matches!(
    -            result,
    -            Ok(true),
    -            "Should finalize the input since we can produce signatures"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_taproot_sign_using_non_witness_utxo() {
    -        let (wallet, _, prev_txid) = get_funded_wallet(get_test_tr_single_sig());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        psbt.inputs[0].witness_utxo = None;
    -        psbt.inputs[0].non_witness_utxo = wallet.database().get_raw_tx(&prev_txid).unwrap();
    -        assert!(
    -            psbt.inputs[0].non_witness_utxo.is_some(),
    -            "Previous tx should be present in the database"
    -        );
    -
    -        let result = wallet.sign(&mut psbt, Default::default());
    -        assert!(result.is_ok(), "Signing should have worked");
    -        assert!(
    -            result.unwrap(),
    -            "Should finalize the input since we can produce signatures"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_taproot_foreign_utxo() {
    -        let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
    -        let (wallet2, _, _) = get_funded_wallet(get_test_tr_single_sig());
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let utxo = wallet2.list_unspent().unwrap().remove(0);
    -        let psbt_input = wallet2.get_psbt_input(utxo.clone(), None, false).unwrap();
    -        let foreign_utxo_satisfaction = wallet2
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -
    -        assert!(
    -            psbt_input.non_witness_utxo.is_none(),
    -            "`non_witness_utxo` should never be populated for taproot"
    -        );
    -
    -        let mut builder = wallet1.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 60_000)
    -            .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
    -            .unwrap();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            details.sent - details.received,
    -            10_000 + details.fee.unwrap_or(0),
    -            "we should have only net spent ~10_000"
    -        );
    -
    -        assert!(
    -            psbt.unsigned_tx
    -                .input
    -                .iter()
    -                .any(|input| input.previous_output == utxo.outpoint),
    -            "foreign_utxo should be in there"
    -        );
    -    }
    -
    -    fn test_spend_from_wallet(wallet: Wallet<AnyDatabase>) {
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        assert!(
    -            wallet.sign(&mut psbt, Default::default()).unwrap(),
    -            "Unable to finalize tx"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_taproot_key_spend() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
    -        test_spend_from_wallet(wallet);
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
    -        test_spend_from_wallet(wallet);
    -    }
    -
    -    #[test]
    -    fn test_taproot_no_key_spend() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_both_priv());
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        assert!(
    -            wallet
    -                .sign(
    -                    &mut psbt,
    -                    SignOptions {
    -                        sign_with_tap_internal_key: false,
    -                        ..Default::default()
    -                    },
    -                )
    -                .unwrap(),
    -            "Unable to finalize tx"
    -        );
    -
    -        assert!(psbt.inputs.iter().all(|i| i.tap_key_sig.is_none()));
    -    }
    -
    -    #[test]
    -    fn test_taproot_script_spend() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree());
    -        test_spend_from_wallet(wallet);
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_xprv());
    -        test_spend_from_wallet(wallet);
    -    }
    -
    -    #[test]
    -    fn test_taproot_script_spend_sign_all_leaves() {
    -        use crate::signer::TapLeavesOptions;
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_both_priv());
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        assert!(
    -            wallet
    -                .sign(
    -                    &mut psbt,
    -                    SignOptions {
    -                        tap_leaves_options: TapLeavesOptions::All,
    -                        ..Default::default()
    -                    },
    -                )
    -                .unwrap(),
    -            "Unable to finalize tx"
    -        );
    -
    -        assert!(psbt
    -            .inputs
    -            .iter()
    -            .all(|i| i.tap_script_sigs.len() == i.tap_scripts.len()));
    -    }
    -
    -    #[test]
    -    fn test_taproot_script_spend_sign_include_some_leaves() {
    -        use crate::signer::TapLeavesOptions;
    -        use bitcoin::util::taproot::TapLeafHash;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_both_priv());
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        let mut script_leaves: Vec<_> = psbt.inputs[0]
    -            .tap_scripts
    -            .clone()
    -            .values()
    -            .map(|(script, version)| TapLeafHash::from_script(script, *version))
    -            .collect();
    -        let included_script_leaves = vec![script_leaves.pop().unwrap()];
    -        let excluded_script_leaves = script_leaves;
    -
    -        assert!(
    -            wallet
    -                .sign(
    -                    &mut psbt,
    -                    SignOptions {
    -                        tap_leaves_options: TapLeavesOptions::Include(
    -                            included_script_leaves.clone()
    -                        ),
    -                        ..Default::default()
    -                    },
    -                )
    -                .unwrap(),
    -            "Unable to finalize tx"
    -        );
    -
    -        assert!(psbt.inputs[0]
    -            .tap_script_sigs
    -            .iter()
    -            .all(|s| included_script_leaves.contains(&s.0 .1)
    -                && !excluded_script_leaves.contains(&s.0 .1)));
    -    }
    -
    -    #[test]
    -    fn test_taproot_script_spend_sign_exclude_some_leaves() {
    -        use crate::signer::TapLeavesOptions;
    -        use bitcoin::util::taproot::TapLeafHash;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_both_priv());
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        let mut script_leaves: Vec<_> = psbt.inputs[0]
    -            .tap_scripts
    -            .clone()
    -            .values()
    -            .map(|(script, version)| TapLeafHash::from_script(script, *version))
    -            .collect();
    -        let included_script_leaves = vec![script_leaves.pop().unwrap()];
    -        let excluded_script_leaves = script_leaves;
    -
    -        assert!(
    -            wallet
    -                .sign(
    -                    &mut psbt,
    -                    SignOptions {
    -                        tap_leaves_options: TapLeavesOptions::Exclude(
    -                            excluded_script_leaves.clone()
    -                        ),
    -                        ..Default::default()
    -                    },
    -                )
    -                .unwrap(),
    -            "Unable to finalize tx"
    -        );
    -
    -        assert!(psbt.inputs[0]
    -            .tap_script_sigs
    -            .iter()
    -            .all(|s| included_script_leaves.contains(&s.0 .1)
    -                && !excluded_script_leaves.contains(&s.0 .1)));
    -    }
    -
    -    #[test]
    -    fn test_taproot_script_spend_sign_no_leaves() {
    -        use crate::signer::TapLeavesOptions;
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_with_taptree_both_priv());
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        wallet
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    tap_leaves_options: TapLeavesOptions::None,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -
    -        assert!(psbt.inputs.iter().all(|i| i.tap_script_sigs.is_empty()));
    -    }
    -
    -    #[test]
    -    fn test_taproot_sign_derive_index_from_psbt() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig_xprv());
    -
    -        let addr = wallet.get_address(AddressIndex::New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        // re-create the wallet with an empty db
    -        let wallet_empty = Wallet::new(
    -            get_test_tr_single_sig_xprv(),
    -            None,
    -            Network::Regtest,
    -            AnyDatabase::Memory(MemoryDatabase::new()),
    -        )
    -        .unwrap();
    -
    -        // signing with an empty db means that we will only look at the psbt to infer the
    -        // derivation index
    -        assert!(
    -            wallet_empty.sign(&mut psbt, Default::default()).unwrap(),
    -            "Unable to finalize tx"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_taproot_sign_explicit_sighash_all() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .sighash(SchnorrSighashType::All.into())
    -            .drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let result = wallet.sign(&mut psbt, Default::default());
    -        assert!(
    -            result.is_ok(),
    -            "Signing should work because SIGHASH_ALL is safe"
    -        )
    -    }
    -
    -    #[test]
    -    fn test_taproot_sign_non_default_sighash() {
    -        let sighash = SchnorrSighashType::NonePlusAnyoneCanPay;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_single_sig());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .sighash(sighash.into())
    -            .drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let witness_utxo = psbt.inputs[0].witness_utxo.take();
    -
    -        let result = wallet.sign(&mut psbt, Default::default());
    -        assert!(
    -            result.is_err(),
    -            "Signing should have failed because the TX uses non-standard sighashes"
    -        );
    -        assert_matches!(
    -            result,
    -            Err(Error::Signer(SignerError::NonStandardSighash)),
    -            "Signing failed with the wrong error type"
    -        );
    -
    -        // try again after opting-in
    -        let result = wallet.sign(
    -            &mut psbt,
    -            SignOptions {
    -                allow_all_sighashes: true,
    -                ..Default::default()
    -            },
    -        );
    -        assert!(
    -            result.is_err(),
    -            "Signing should have failed because the witness_utxo is missing"
    -        );
    -        assert_matches!(
    -            result,
    -            Err(Error::Signer(SignerError::MissingWitnessUtxo)),
    -            "Signing failed with the wrong error type"
    -        );
    -
    -        // restore the witness_utxo
    -        psbt.inputs[0].witness_utxo = witness_utxo;
    -
    -        let result = wallet.sign(
    -            &mut psbt,
    -            SignOptions {
    -                allow_all_sighashes: true,
    -                ..Default::default()
    -            },
    -        );
    -
    -        assert!(result.is_ok(), "Signing should have worked");
    -        assert!(
    -            result.unwrap(),
    -            "Should finalize the input since we can produce signatures"
    -        );
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(
    -            *extracted.input[0].witness.to_vec()[0].last().unwrap(),
    -            sighash as u8,
    -            "The signature should have been made with the right sighash"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_spend_coinbase() {
    -        let descriptors = testutils!(@descriptors (get_test_wpkh()));
    -        let wallet = Wallet::new(
    -            &descriptors.0,
    -            None,
    -            Network::Regtest,
    -            AnyDatabase::Memory(MemoryDatabase::new()),
    -        )
    -        .unwrap();
    -
    -        let confirmation_time = 5;
    -
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(confirmation_time),
    -            (@coinbase true)
    -        );
    -        let sync_time = SyncTime {
    -            block_time: BlockTime {
    -                height: confirmation_time,
    -                timestamp: 0,
    -            },
    -        };
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_sync_time(sync_time)
    -            .unwrap();
    -
    -        let not_yet_mature_time = confirmation_time + COINBASE_MATURITY - 1;
    -        let maturity_time = confirmation_time + COINBASE_MATURITY;
    -
    -        let balance = wallet.get_balance().unwrap();
    -        assert_eq!(
    -            balance,
    -            Balance {
    -                immature: 25_000,
    -                trusted_pending: 0,
    -                untrusted_pending: 0,
    -                confirmed: 0
    -            }
    -        );
    -
    -        // We try to create a transaction, only to notice that all
    -        // our funds are unspendable
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), balance.immature / 2)
    -            .current_height(confirmation_time);
    -        assert_matches!(
    -            builder.finish(),
    -            Err(Error::InsufficientFunds {
    -                needed: _,
    -                available: 0
    -            })
    -        );
    -
    -        // Still unspendable...
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), balance.immature / 2)
    -            .current_height(not_yet_mature_time);
    -        assert_matches!(
    -            builder.finish(),
    -            Err(Error::InsufficientFunds {
    -                needed: _,
    -                available: 0
    -            })
    -        );
    -
    -        // ...Now the coinbase is mature :)
    -        let sync_time = SyncTime {
    -            block_time: BlockTime {
    -                height: maturity_time,
    -                timestamp: 0,
    -            },
    -        };
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_sync_time(sync_time)
    -            .unwrap();
    -
    -        let balance = wallet.get_balance().unwrap();
    -        assert_eq!(
    -            balance,
    -            Balance {
    -                immature: 0,
    -                trusted_pending: 0,
    -                untrusted_pending: 0,
    -                confirmed: 25_000
    -            }
    -        );
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), balance.confirmed / 2)
    -            .current_height(maturity_time);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_allow_dust_limit() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -
    -        let addr = wallet.get_address(New).unwrap();
    -
    -        let mut builder = wallet.build_tx();
    -
    -        builder.add_recipient(addr.script_pubkey(), 0);
    -
    -        assert_matches!(builder.finish(), Err(Error::OutputBelowDustLimit(0)));
    -
    -        let mut builder = wallet.build_tx();
    -
    -        builder
    -            .allow_dust(true)
    -            .add_recipient(addr.script_pubkey(), 0);
    -
    -        assert!(builder.finish().is_ok());
    -    }
    -
    -    #[test]
    -    fn test_fee_rate_sign_no_grinding_high_r() {
    -        // Our goal is to obtain a transaction with a signature with high-R (71 bytes
    -        // instead of 70). We then check that our fee rate and fee calculation is
    -        // alright.
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let fee_rate = FeeRate::from_sat_per_vb(1.0);
    -        let mut builder = wallet.build_tx();
    -        let mut data = vec![0];
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_rate(fee_rate)
    -            .add_data(&data);
    -        let (mut psbt, details) = builder.finish().unwrap();
    -        let (op_return_vout, _) = psbt
    -            .unsigned_tx
    -            .output
    -            .iter()
    -            .enumerate()
    -            .find(|(_n, i)| i.script_pubkey.is_op_return())
    -            .unwrap();
    -
    -        let mut sig_len: usize = 0;
    -        // We try to sign many different times until we find a longer signature (71 bytes)
    -        while sig_len < 71 {
    -            // Changing the OP_RETURN data will make the signature change (but not the fee, until
    -            // data[0] is small enough)
    -            data[0] += 1;
    -            psbt.unsigned_tx.output[op_return_vout].script_pubkey = Script::new_op_return(&data);
    -            // Clearing the previous signature
    -            psbt.inputs[0].partial_sigs.clear();
    -            // Signing
    -            wallet
    -                .sign(
    -                    &mut psbt,
    -                    SignOptions {
    -                        remove_partial_sigs: false,
    -                        try_finalize: false,
    -                        allow_grinding: false,
    -                        ..Default::default()
    -                    },
    -                )
    -                .unwrap();
    -            // We only have one key in the partial_sigs map, this is a trick to retrieve it
    -            let key = psbt.inputs[0].partial_sigs.keys().next().unwrap();
    -            sig_len = psbt.inputs[0].partial_sigs[key].sig.serialize_der().len();
    -        }
    -        // Actually finalizing the transaction...
    -        wallet
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    remove_partial_sigs: false,
    -                    allow_grinding: false,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -        // ...and checking that everything is fine
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate);
    -    }
    -
    -    #[test]
    -    fn test_fee_rate_sign_grinding_low_r() {
    -        // Our goal is to obtain a transaction with a signature with low-R (70 bytes)
    -        // by setting the `allow_grinding` signing option as true.
    -        // We then check that our fee rate and fee calculation is alright and that our
    -        // signature is 70 bytes.
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let fee_rate = FeeRate::from_sat_per_vb(1.0);
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_rate(fee_rate);
    -        let (mut psbt, details) = builder.finish().unwrap();
    -
    -        wallet
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    remove_partial_sigs: false,
    -                    allow_grinding: true,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -
    -        let key = psbt.inputs[0].partial_sigs.keys().next().unwrap();
    -        let sig_len = psbt.inputs[0].partial_sigs[key].sig.serialize_der().len();
    -        assert_eq!(sig_len, 70);
    -        assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate);
    -    }
    -
    -    #[cfg(feature = "test-hardware-signer")]
    -    #[test]
    -    fn test_create_signer() {
    -        use crate::wallet::hardwaresigner::HWISigner;
    -        use hwi::types::HWIChain;
    -        use hwi::HWIClient;
    -
    -        let mut devices = HWIClient::enumerate().unwrap();
    -        if devices.is_empty() {
    -            panic!("No devices found!");
    -        }
    -        let device = devices.remove(0).unwrap();
    -        let client = HWIClient::get_client(&device, true, HWIChain::Regtest).unwrap();
    -        let descriptors = client.get_descriptors::<String>(None).unwrap();
    -        let custom_signer = HWISigner::from_device(&device, HWIChain::Regtest).unwrap();
    -
    -        let (mut wallet, _, _) = get_funded_wallet(&descriptors.internal[0]);
    -        wallet.add_signer(
    -            KeychainKind::External,
    -            SignerOrdering(200),
    -            Arc::new(custom_signer),
    -        );
    -
    -        let addr = wallet.get_address(LastUnused).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -    }
    -
    -    #[test]
    -    fn test_taproot_load_descriptor_duplicated_keys() {
    -        // Added after issue https://github.com/bitcoindevkit/bdk/issues/760
    -        //
    -        // Having the same key in multiple taproot leaves is safe and should be accepted by BDK
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_tr_dup_keys());
    -        let addr = wallet.get_address(New).unwrap();
    -
    -        assert_eq!(
    -            addr.to_string(),
    -            "bcrt1pvysh4nmh85ysrkpwtrr8q8gdadhgdejpy6f9v424a8v9htjxjhyqw9c5s5"
    -        );
    -    }
    +    }}
     }
     
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html index 411f5ff9e4..c4baa835d2 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html @@ -1,5 +1,4 @@ -signer.rs - source
    1
    +signer.rs - source
    1
     2
     3
     4
    @@ -1138,6 +1137,7 @@
     1137
     1138
     1139
    +1140
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -1155,13 +1155,12 @@
     //! through the [`Wallet::add_signer`](super::Wallet::add_signer) function.
     //!
     //! ```
    -//! # use std::sync::Arc;
    -//! # use std::str::FromStr;
    +//! # use alloc::sync::Arc;
    +//! # use core::str::FromStr;
     //! # use bitcoin::secp256k1::{Secp256k1, All};
     //! # use bitcoin::*;
     //! # use bitcoin::util::psbt;
     //! # use bdk::signer::*;
    -//! # use bdk::database::*;
     //! # use bdk::*;
     //! # #[derive(Debug)]
     //! # struct CustomHSM;
    @@ -1210,7 +1209,7 @@
     //! let custom_signer = CustomSigner::connect();
     //!
     //! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -//! let mut wallet = Wallet::new(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    +//! let mut wallet = Wallet::new_no_persist(descriptor, None, Network::Testnet)?;
     //! wallet.add_signer(
     //!     KeychainKind::External,
     //!     SignerOrdering(200),
    @@ -1220,11 +1219,12 @@
     //! # Ok::<_, bdk::Error>(())
     //! ```
     
    -use std::cmp::Ordering;
    -use std::collections::BTreeMap;
    -use std::fmt;
    -use std::ops::{Bound::Included, Deref};
    -use std::sync::Arc;
    +use crate::collections::BTreeMap;
    +use alloc::sync::Arc;
    +use alloc::vec::Vec;
    +use core::cmp::Ordering;
    +use core::fmt;
    +use core::ops::{Bound::Included, Deref};
     
     use bitcoin::blockdata::opcodes;
     use bitcoin::blockdata::script::Builder as ScriptBuilder;
    @@ -1339,7 +1339,8 @@
         }
     }
     
    -impl std::error::Error for SignerError {}
    +#[cfg(feature = "std")]
    +impl std::error::Error for SignerError {}
     
     /// Signing context
     ///
    @@ -1700,7 +1701,7 @@
     #[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
     pub struct SignerOrdering(pub usize);
     
    -impl std::default::Default for SignerOrdering {
    +impl Default for SignerOrdering {
         fn default() -> Self {
             SignerOrdering(100)
         }
    @@ -2157,8 +2158,8 @@
         use bitcoin::secp256k1::{All, Secp256k1};
         use bitcoin::util::bip32;
         use bitcoin::Network;
    +    use core::str::FromStr;
         use miniscript::ScriptContext;
    -    use std::str::FromStr;
     
         fn is_equal(this: &Arc<dyn TransactionSigner>, that: &Arc<DummySigner>) -> bool {
             let secp = Secp256k1::new();
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html
    deleted file mode 100644
    index febcebe3cd..0000000000
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html
    +++ /dev/null
    @@ -1,149 +0,0 @@
    -time.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Cross-platform time
    -//!
    -//! This module provides a function to get the current timestamp that works on all the platforms
    -//! supported by the library.
    -//!
    -//! It can be useful to compare it with the timestamps found in
    -//! [`TransactionDetails`](crate::types::TransactionDetails).
    -
    -use std::time::Duration;
    -
    -#[cfg(target_arch = "wasm32")]
    -use js_sys::Date;
    -#[cfg(not(target_arch = "wasm32"))]
    -use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
    -
    -/// Return the current timestamp in seconds
    -#[cfg(not(target_arch = "wasm32"))]
    -pub fn get_timestamp() -> u64 {
    -    SystemTime::now()
    -        .duration_since(UNIX_EPOCH)
    -        .unwrap()
    -        .as_secs()
    -}
    -/// Return the current timestamp in seconds
    -#[cfg(target_arch = "wasm32")]
    -pub fn get_timestamp() -> u64 {
    -    let millis = Date::now();
    -
    -    (millis / 1000.0) as u64
    -}
    -
    -#[cfg(not(target_arch = "wasm32"))]
    -pub(crate) struct Instant(SystemInstant);
    -#[cfg(target_arch = "wasm32")]
    -pub(crate) struct Instant(Duration);
    -
    -impl Instant {
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn new() -> Self {
    -        Instant(SystemInstant::now())
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn new() -> Self {
    -        let millis = Date::now();
    -
    -        let secs = millis / 1000.0;
    -        let nanos = (millis % 1000.0) * 1e6;
    -
    -        Instant(Duration::new(secs as u64, nanos as u32))
    -    }
    -
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn elapsed(&self) -> Duration {
    -        self.0.elapsed()
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn elapsed(&self) -> Duration {
    -        let now = Instant::new();
    -
    -        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html index 6287c0ea19..921663255b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html @@ -1,5 +1,4 @@ -tx_builder.rs - source
    1
    +tx_builder.rs - source
    1
     2
     3
     4
    @@ -922,6 +921,27 @@
     921
     922
     923
    +924
    +925
    +926
    +927
    +928
    +929
    +930
    +931
    +932
    +933
    +934
    +935
    +936
    +937
    +938
    +939
    +940
    +941
    +942
    +943
    +944
     
    // Bitcoin Dev Kit
     // Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
     //
    @@ -943,7 +963,7 @@
     //! # use bdk::*;
     //! # use bdk::wallet::tx_builder::CreateTx;
     //! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -//! # let wallet = doctest_wallet!();
    +//! # let mut wallet = doctest_wallet!();
     //! // create a TxBuilder from a wallet
     //! let mut tx_builder = wallet.build_tx();
     //!
    @@ -960,22 +980,25 @@
     //! # Ok::<(), bdk::Error>(())
     //! ```
     
    -use std::collections::BTreeMap;
    -use std::collections::HashSet;
    -use std::default::Default;
    -use std::marker::PhantomData;
    +use crate::collections::BTreeMap;
    +use crate::collections::HashSet;
    +use alloc::{boxed::Box, rc::Rc, string::String, vec::Vec};
    +use bdk_chain::ConfirmationTime;
    +use core::cell::RefCell;
    +use core::marker::PhantomData;
     
     use bitcoin::util::psbt::{self, PartiallySignedTransaction as Psbt};
     use bitcoin::{LockTime, OutPoint, Script, Sequence, Transaction};
     
     use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
    -use crate::{database::BatchDatabase, Error, Utxo, Wallet};
    +use super::persist;
     use crate::{
         types::{FeeRate, KeychainKind, LocalUtxo, WeightedUtxo},
         TransactionDetails,
     };
    +use crate::{Error, Utxo, Wallet};
     /// Context in which the [`TxBuilder`] is valid
    -pub trait TxBuilderContext: std::fmt::Debug + Default + Clone {}
    +pub trait TxBuilderContext: core::fmt::Debug + Default + Clone {}
     
     /// Marker type to indicate the [`TxBuilder`] is being used to create a new transaction (as opposed
     /// to bumping the fee of an existing one).
    @@ -1002,7 +1025,7 @@
     /// # use bdk::wallet::tx_builder::*;
     /// # use bitcoin::*;
     /// # use core::str::FromStr;
    -/// # let wallet = doctest_wallet!();
    +/// # let mut wallet = doctest_wallet!();
     /// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
     /// # let addr2 = addr1.clone();
     /// // chaining
    @@ -1040,7 +1063,7 @@
     /// [`coin_selection`]: Self::coin_selection
     #[derive(Debug)]
     pub struct TxBuilder<'a, D, Cs, Ctx> {
    -    pub(crate) wallet: &'a Wallet<D>,
    +    pub(crate) wallet: Rc<RefCell<&'a mut Wallet<D>>>,
         pub(crate) params: TxParams,
         pub(crate) coin_selection: Cs,
         pub(crate) phantom: PhantomData<Ctx>,
    @@ -1085,16 +1108,16 @@
         FeeAmount(u64),
     }
     
    -impl std::default::Default for FeePolicy {
    +impl Default for FeePolicy {
         fn default() -> Self {
             FeePolicy::FeeRate(FeeRate::default_min_relay_fee())
         }
     }
     
    -impl<'a, Cs: Clone, Ctx, D> Clone for TxBuilder<'a, D, Cs, Ctx> {
    +impl<'a, D, Cs: Clone, Ctx> Clone for TxBuilder<'a, D, Cs, Ctx> {
         fn clone(&self) -> Self {
             TxBuilder {
    -            wallet: self.wallet,
    +            wallet: self.wallet.clone(),
                 params: self.params.clone(),
                 coin_selection: self.coin_selection.clone(),
                 phantom: PhantomData,
    @@ -1103,9 +1126,7 @@
     }
     
     // methods supported by both contexts, for any CoinSelectionAlgorithm
    -impl<'a, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext>
    -    TxBuilder<'a, D, Cs, Ctx>
    -{
    +impl<'a, D, Cs: CoinSelectionAlgorithm, Ctx: TxBuilderContext> TxBuilder<'a, D, Cs, Ctx> {
         /// Set a custom fee rate
         pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self {
             self.params.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
    @@ -1166,7 +1187,7 @@
         /// # use bitcoin::*;
         /// # use bdk::*;
         /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// # let wallet = doctest_wallet!();
    +    /// # let mut wallet = doctest_wallet!();
         /// let mut path = BTreeMap::new();
         /// path.insert("aabbccdd".to_string(), vec![0, 1]);
         ///
    @@ -1198,18 +1219,21 @@
         /// These have priority over the "unspendable" utxos, meaning that if a utxo is present both in
         /// the "utxos" and the "unspendable" list, it will be spent.
         pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, Error> {
    -        let utxos = outpoints
    -            .iter()
    -            .map(|outpoint| self.wallet.get_utxo(*outpoint)?.ok_or(Error::UnknownUtxo))
    -            .collect::<Result<Vec<_>, _>>()?;
    -
    -        for utxo in utxos {
    -            let descriptor = self.wallet.get_descriptor_for_keychain(utxo.keychain);
    -            let satisfaction_weight = descriptor.max_satisfaction_weight().unwrap();
    -            self.params.utxos.push(WeightedUtxo {
    -                satisfaction_weight,
    -                utxo: Utxo::Local(utxo),
    -            });
    +        {
    +            let wallet = self.wallet.borrow();
    +            let utxos = outpoints
    +                .iter()
    +                .map(|outpoint| wallet.get_utxo(*outpoint).ok_or(Error::UnknownUtxo))
    +                .collect::<Result<Vec<_>, _>>()?;
    +
    +            for utxo in utxos {
    +                let descriptor = wallet.get_descriptor_for_keychain(utxo.keychain);
    +                let satisfaction_weight = descriptor.max_satisfaction_weight().unwrap();
    +                self.params.utxos.push(WeightedUtxo {
    +                    satisfaction_weight,
    +                    utxo: Utxo::Local(utxo),
    +                });
    +            }
             }
     
             Ok(self)
    @@ -1427,7 +1451,7 @@
         /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
         ///
         /// Note that this function consumes the builder and returns it so it is usually best to put this as the first call on the builder.
    -    pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
    +    pub fn coin_selection<P: CoinSelectionAlgorithm>(
             self,
             coin_selection: P,
         ) -> TxBuilder<'a, D, P, Ctx> {
    @@ -1444,8 +1468,13 @@
         /// Returns the [`BIP174`] "PSBT" and summary details about the transaction.
         ///
         /// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
    -    pub fn finish(self) -> Result<(Psbt, TransactionDetails), Error> {
    -        self.wallet.create_tx(self.coin_selection, self.params)
    +    pub fn finish(self) -> Result<(Psbt, TransactionDetails), Error>
    +    where
    +        D: persist::PersistBackend<KeychainKind, ConfirmationTime>,
    +    {
    +        self.wallet
    +            .borrow_mut()
    +            .create_tx(self.coin_selection, self.params)
         }
     
         /// Enable signaling RBF
    @@ -1493,7 +1522,7 @@
         }
     }
     
    -impl<'a, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, D, Cs, CreateTx> {
    +impl<'a, D, Cs: CoinSelectionAlgorithm> TxBuilder<'a, D, Cs, CreateTx> {
         /// Replace the recipients already added with a new list
         pub fn set_recipients(&mut self, recipients: Vec<(Script, u64)>) -> &mut Self {
             self.params.recipients = recipients;
    @@ -1539,7 +1568,7 @@
         /// # use bdk::*;
         /// # use bdk::wallet::tx_builder::CreateTx;
         /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// # let wallet = doctest_wallet!();
    +    /// # let mut wallet = doctest_wallet!();
         /// let mut tx_builder = wallet.build_tx();
         ///
         /// tx_builder
    @@ -1564,7 +1593,7 @@
     }
     
     // methods supported only by bump_fee
    -impl<'a, D: BatchDatabase> TxBuilder<'a, D, DefaultCoinSelectionAlgorithm, BumpFee> {
    +impl<'a, D> TxBuilder<'a, D, DefaultCoinSelectionAlgorithm, BumpFee> {
         /// Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this
         /// `script_pubkey` in order to bump the transaction fee. Without specifying this the wallet
         /// will attempt to find a change output to shrink instead.
    @@ -1619,14 +1648,8 @@
                 TxOrdering::Untouched => {}
                 TxOrdering::Shuffle => {
                     use rand::seq::SliceRandom;
    -                #[cfg(test)]
    -                use rand::SeedableRng;
    -
    -                #[cfg(not(test))]
    -                let mut rng = rand::thread_rng();
    -                #[cfg(test)]
    -                let mut rng = rand::rngs::StdRng::seed_from_u64(12345);
    -
    +                let mut rng = rand::thread_rng();
    +                tx.input.shuffle(&mut rng);
                     tx.output.shuffle(&mut rng);
                 }
                 TxOrdering::Bip69Lexicographic => {
    @@ -1712,6 +1735,7 @@
             };
         }
     
    +    use bdk_chain::ConfirmationTime;
         use bitcoin::consensus::deserialize;
         use bitcoin::hashes::hex::FromHex;
     
    @@ -1737,15 +1761,25 @@
             let original_tx = ordering_test_tx!();
             let mut tx = original_tx.clone();
     
    -        TxOrdering::Shuffle.sort_tx(&mut tx);
    +        (0..40)
    +            .find(|_| {
    +                TxOrdering::Shuffle.sort_tx(&mut tx);
    +                original_tx.input != tx.input
    +            })
    +            .expect("it should have moved the inputs at least once");
     
    -        assert_eq!(original_tx.input, tx.input);
    -        assert_ne!(original_tx.output, tx.output);
    +        let mut tx = original_tx.clone();
    +        (0..40)
    +            .find(|_| {
    +                TxOrdering::Shuffle.sort_tx(&mut tx);
    +                original_tx.output != tx.output
    +            })
    +            .expect("it should have moved the outputs at least once");
         }
     
         #[test]
         fn test_output_ordering_bip69() {
    -        use std::str::FromStr;
    +        use core::str::FromStr;
     
             let original_tx = ordering_test_tx!();
             let mut tx = original_tx;
    @@ -1791,6 +1825,8 @@
                     txout: Default::default(),
                     keychain: KeychainKind::External,
                     is_spent: false,
    +                confirmation_time: ConfirmationTime::Unconfirmed,
    +                derivation_index: 0,
                 },
                 LocalUtxo {
                     outpoint: OutPoint {
    @@ -1800,6 +1836,11 @@
                     txout: Default::default(),
                     keychain: KeychainKind::Internal,
                     is_spent: false,
    +                confirmation_time: ConfirmationTime::Confirmed {
    +                    height: 32,
    +                    time: 42,
    +                },
    +                derivation_index: 1,
                 },
             ]
         }
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html
    index c4d635112c..0359e6bd23 100644
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html
    +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html
    @@ -1,5 +1,4 @@
    -utils.rs - source
    1
    +utils.rs - source
    1
     2
     3
     4
    @@ -302,7 +301,7 @@
     
         use super::{check_nsequence_rbf, IsDust};
         use crate::bitcoin::{Address, Sequence};
    -    use std::str::FromStr;
    +    use core::str::FromStr;
     
         #[test]
         fn test_is_dust() {
    diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/verify.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/verify.rs.html
    deleted file mode 100644
    index d3bb725e41..0000000000
    --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/verify.rs.html
    +++ /dev/null
    @@ -1,335 +0,0 @@
    -verify.rs - source
    1
    -2
    -3
    -4
    -5
    -6
    -7
    -8
    -9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -87
    -88
    -89
    -90
    -91
    -92
    -93
    -94
    -95
    -96
    -97
    -98
    -99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -
    // Bitcoin Dev Kit
    -// Written in 2021 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Verify transactions against the consensus rules
    -
    -use std::collections::HashMap;
    -use std::fmt;
    -
    -use bitcoin::consensus::serialize;
    -use bitcoin::{OutPoint, Transaction, Txid};
    -
    -use crate::blockchain::GetTx;
    -use crate::database::Database;
    -use crate::error::Error;
    -
    -/// Verify a transaction against the consensus rules
    -///
    -/// This function uses [`bitcoinconsensus`] to verify transactions by fetching the required data
    -/// either from the [`Database`] or using the [`Blockchain`].
    -///
    -/// Depending on the [capabilities](crate::blockchain::Blockchain::get_capabilities) of the
    -/// [`Blockchain`] backend, the method could fail when called with old "historical" transactions or
    -/// with unconfirmed transactions that have been evicted from the backend's memory.
    -///
    -/// [`Blockchain`]: crate::blockchain::Blockchain
    -pub fn verify_tx<D: Database, B: GetTx>(
    -    tx: &Transaction,
    -    database: &D,
    -    blockchain: &B,
    -) -> Result<(), VerifyError> {
    -    log::debug!("Verifying {}", tx.txid());
    -
    -    let serialized_tx = serialize(tx);
    -    let mut tx_cache = HashMap::<_, Transaction>::new();
    -
    -    for (index, input) in tx.input.iter().enumerate() {
    -        let prev_tx = if let Some(prev_tx) = tx_cache.get(&input.previous_output.txid) {
    -            prev_tx.clone()
    -        } else if let Some(prev_tx) = database.get_raw_tx(&input.previous_output.txid)? {
    -            prev_tx
    -        } else if let Some(prev_tx) = blockchain.get_tx(&input.previous_output.txid)? {
    -            prev_tx
    -        } else {
    -            return Err(VerifyError::MissingInputTx(input.previous_output.txid));
    -        };
    -
    -        let spent_output = prev_tx
    -            .output
    -            .get(input.previous_output.vout as usize)
    -            .ok_or(VerifyError::InvalidInput(input.previous_output))?;
    -
    -        bitcoinconsensus::verify(
    -            &spent_output.script_pubkey.to_bytes(),
    -            spent_output.value,
    -            &serialized_tx,
    -            index,
    -        )?;
    -
    -        // Since we have a local cache we might as well cache stuff from the db, as it will very
    -        // likely decrease latency compared to reading from disk or performing an SQL query.
    -        tx_cache.insert(prev_tx.txid(), prev_tx);
    -    }
    -
    -    Ok(())
    -}
    -
    -/// Error during validation of a tx agains the consensus rules
    -#[derive(Debug)]
    -pub enum VerifyError {
    -    /// The transaction being spent is not available in the database or the blockchain client
    -    MissingInputTx(Txid),
    -    /// The transaction being spent doesn't have the requested output
    -    InvalidInput(OutPoint),
    -
    -    /// Consensus error
    -    Consensus(bitcoinconsensus::Error),
    -
    -    /// Generic error
    -    ///
    -    /// It has to be wrapped in a `Box` since `Error` has a variant that contains this enum
    -    Global(Box<Error>),
    -}
    -
    -impl fmt::Display for VerifyError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        match self {
    -            Self::MissingInputTx(txid) => write!(f, "The transaction being spent is not available in the database or the blockchain client: {}", txid),
    -            Self::InvalidInput(outpoint) => write!(f, "The transaction being spent doesn't have the requested output: {}", outpoint),
    -            Self::Consensus(err) => write!(f, "Consensus error: {:?}", err),
    -            Self::Global(err) => write!(f, "Generic error: {}", err),
    -        }
    -    }
    -}
    -
    -impl std::error::Error for VerifyError {}
    -
    -impl From<Error> for VerifyError {
    -    fn from(other: Error) -> Self {
    -        VerifyError::Global(Box::new(other))
    -    }
    -}
    -impl_error!(bitcoinconsensus::Error, Consensus, VerifyError);
    -
    -#[cfg(test)]
    -mod test {
    -    use super::*;
    -    use crate::database::{BatchOperations, MemoryDatabase};
    -    use assert_matches::assert_matches;
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::hashes::hex::FromHex;
    -    use bitcoin::{Transaction, Txid};
    -
    -    struct DummyBlockchain;
    -
    -    impl GetTx for DummyBlockchain {
    -        fn get_tx(&self, _txid: &Txid) -> Result<Option<Transaction>, Error> {
    -            Ok(None)
    -        }
    -    }
    -
    -    #[test]
    -    fn test_verify_fail_unsigned_tx() {
    -        // https://blockstream.info/tx/95da344585fcf2e5f7d6cbf2c3df2dcce84f9196f7a7bb901a43275cd6eb7c3f
    -        let prev_tx: Transaction = deserialize(&Vec::<u8>::from_hex("020000000101192dea5e66d444380e106f8e53acb171703f00d43fb6b3ae88ca5644bdb7e1000000006b48304502210098328d026ce138411f957966c1cf7f7597ccbb170f5d5655ee3e9f47b18f6999022017c3526fc9147830e1340e04934476a3d1521af5b4de4e98baf49ec4c072079e01210276f847f77ec8dd66d78affd3c318a0ed26d89dab33fa143333c207402fcec352feffffff023d0ac203000000001976a9144bfbaf6afb76cc5771bc6404810d1cc041a6933988aca4b956050000000017a91494d5543c74a3ee98e0cf8e8caef5dc813a0f34b48768cb0700").unwrap()).unwrap();
    -        // https://blockstream.info/tx/aca326a724eda9a461c10a876534ecd5ae7b27f10f26c3862fb996f80ea2d45d
    -        let signed_tx: Transaction = deserialize(&Vec::<u8>::from_hex("02000000013f7cebd65c27431a90bba7f796914fe8cc2ddfc3f2cbd6f7e5f2fc854534da95000000006b483045022100de1ac3bcdfb0332207c4a91f3832bd2c2915840165f876ab47c5f8996b971c3602201c6c053d750fadde599e6f5c4e1963df0f01fc0d97815e8157e3d59fe09ca30d012103699b464d1d8bc9e47d4fb1cdaa89a1c5783d68363c4dbc4b524ed3d857148617feffffff02836d3c01000000001976a914fc25d6d5c94003bf5b0c7b640a248e2c637fcfb088ac7ada8202000000001976a914fbed3d9b11183209a57999d54d59f67c019e756c88ac6acb0700").unwrap()).unwrap();
    -
    -        let mut database = MemoryDatabase::new();
    -        let blockchain = DummyBlockchain;
    -
    -        let mut unsigned_tx = signed_tx.clone();
    -        for input in &mut unsigned_tx.input {
    -            input.script_sig = Default::default();
    -            input.witness = Default::default();
    -        }
    -
    -        let result = verify_tx(&signed_tx, &database, &blockchain);
    -        assert_matches!(result, Err(VerifyError::MissingInputTx(txid)) if txid == prev_tx.txid(),
    -            "Error should be a `MissingInputTx` error"
    -        );
    -
    -        // insert the prev_tx
    -        database.set_raw_tx(&prev_tx).unwrap();
    -
    -        let result = verify_tx(&unsigned_tx, &database, &blockchain);
    -        assert_matches!(
    -            result,
    -            Err(VerifyError::Consensus(_)),
    -            "Error should be a `Consensus` error"
    -        );
    -
    -        let result = verify_tx(&signed_tx, &database, &blockchain);
    -        assert!(
    -            result.is_ok(),
    -            "Should work since the TX is correctly signed"
    -        );
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/chain_data.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/chain_data.rs.html new file mode 100644 index 0000000000..d585ff1adf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/chain_data.rs.html @@ -0,0 +1,438 @@ +chain_data.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +
    use bitcoin::{hashes::Hash, BlockHash, OutPoint, TxOut, Txid};
    +
    +use crate::{
    +    sparse_chain::{self, ChainPosition},
    +    COINBASE_MATURITY,
    +};
    +
    +/// Represents the height in which a transaction is confirmed at.
    +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(crate = "serde_crate")
    +)]
    +pub enum TxHeight {
    +    Confirmed(u32),
    +    Unconfirmed,
    +}
    +
    +impl Default for TxHeight {
    +    fn default() -> Self {
    +        Self::Unconfirmed
    +    }
    +}
    +
    +impl core::fmt::Display for TxHeight {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            Self::Confirmed(h) => core::write!(f, "confirmed_at({})", h),
    +            Self::Unconfirmed => core::write!(f, "unconfirmed"),
    +        }
    +    }
    +}
    +
    +impl From<Option<u32>> for TxHeight {
    +    fn from(opt: Option<u32>) -> Self {
    +        match opt {
    +            Some(h) => Self::Confirmed(h),
    +            None => Self::Unconfirmed,
    +        }
    +    }
    +}
    +
    +impl From<TxHeight> for Option<u32> {
    +    fn from(height: TxHeight) -> Self {
    +        match height {
    +            TxHeight::Confirmed(h) => Some(h),
    +            TxHeight::Unconfirmed => None,
    +        }
    +    }
    +}
    +
    +impl crate::sparse_chain::ChainPosition for TxHeight {
    +    fn height(&self) -> TxHeight {
    +        *self
    +    }
    +
    +    fn max_ord_of_height(height: TxHeight) -> Self {
    +        height
    +    }
    +
    +    fn min_ord_of_height(height: TxHeight) -> Self {
    +        height
    +    }
    +}
    +
    +impl TxHeight {
    +    pub fn is_confirmed(&self) -> bool {
    +        matches!(self, Self::Confirmed(_))
    +    }
    +}
    +
    +/// Block height and timestamp in which a transaction is confirmed in.
    +#[derive(Debug, Clone, PartialEq, Eq, Copy, PartialOrd, Ord, core::hash::Hash)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(crate = "serde_crate")
    +)]
    +pub enum ConfirmationTime {
    +    Confirmed { height: u32, time: u64 },
    +    Unconfirmed,
    +}
    +
    +impl sparse_chain::ChainPosition for ConfirmationTime {
    +    fn height(&self) -> TxHeight {
    +        match self {
    +            ConfirmationTime::Confirmed { height, .. } => TxHeight::Confirmed(*height),
    +            ConfirmationTime::Unconfirmed => TxHeight::Unconfirmed,
    +        }
    +    }
    +
    +    fn max_ord_of_height(height: TxHeight) -> Self {
    +        match height {
    +            TxHeight::Confirmed(height) => Self::Confirmed {
    +                height,
    +                time: u64::MAX,
    +            },
    +            TxHeight::Unconfirmed => Self::Unconfirmed,
    +        }
    +    }
    +
    +    fn min_ord_of_height(height: TxHeight) -> Self {
    +        match height {
    +            TxHeight::Confirmed(height) => Self::Confirmed {
    +                height,
    +                time: u64::MIN,
    +            },
    +            TxHeight::Unconfirmed => Self::Unconfirmed,
    +        }
    +    }
    +}
    +
    +impl ConfirmationTime {
    +    pub fn is_confirmed(&self) -> bool {
    +        matches!(self, Self::Confirmed { .. })
    +    }
    +}
    +
    +/// A reference to a block in the cannonical chain.
    +#[derive(Debug, Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(crate = "serde_crate")
    +)]
    +pub struct BlockId {
    +    /// The height the block was confirmed at
    +    pub height: u32,
    +    /// The hash of the block
    +    pub hash: BlockHash,
    +}
    +
    +impl Default for BlockId {
    +    fn default() -> Self {
    +        Self {
    +            height: Default::default(),
    +            hash: BlockHash::from_inner([0u8; 32]),
    +        }
    +    }
    +}
    +
    +impl From<(u32, BlockHash)> for BlockId {
    +    fn from((height, hash): (u32, BlockHash)) -> Self {
    +        Self { height, hash }
    +    }
    +}
    +
    +impl From<BlockId> for (u32, BlockHash) {
    +    fn from(block_id: BlockId) -> Self {
    +        (block_id.height, block_id.hash)
    +    }
    +}
    +
    +impl From<(&u32, &BlockHash)> for BlockId {
    +    fn from((height, hash): (&u32, &BlockHash)) -> Self {
    +        Self {
    +            height: *height,
    +            hash: *hash,
    +        }
    +    }
    +}
    +
    +/// A `TxOut` with as much data as we can retreive about it
    +#[derive(Debug, Clone, PartialEq)]
    +pub struct FullTxOut<I> {
    +    /// The location of the `TxOut`
    +    pub outpoint: OutPoint,
    +    /// The `TxOut`
    +    pub txout: TxOut,
    +    /// The position of the transaction in `outpoint` in the overall chain.
    +    pub chain_position: I,
    +    /// The txid and chain position of the transaction (if any) that has spent this output.
    +    pub spent_by: Option<(I, Txid)>,
    +    /// Whether this output is on a coinbase transaction
    +    pub is_on_coinbase: bool,
    +}
    +
    +impl<I: ChainPosition> FullTxOut<I> {
    +    /// Whether the utxo is/was/will be spendable at `height`.
    +    ///
    +    /// It is spendable if it is not an immature coinbase output and no spending tx has been
    +    /// confirmed by that heigt.
    +    pub fn is_spendable_at(&self, height: u32) -> bool {
    +        if !self.is_mature(height) {
    +            return false;
    +        }
    +
    +        if self.chain_position.height() > TxHeight::Confirmed(height) {
    +            return false;
    +        }
    +
    +        match &self.spent_by {
    +            Some((spending_height, _)) => spending_height.height() > TxHeight::Confirmed(height),
    +            None => true,
    +        }
    +    }
    +
    +    pub fn is_mature(&self, height: u32) -> bool {
    +        if self.is_on_coinbase {
    +            let tx_height = match self.chain_position.height() {
    +                TxHeight::Confirmed(tx_height) => tx_height,
    +                TxHeight::Unconfirmed => {
    +                    debug_assert!(false, "coinbase tx can never be unconfirmed");
    +                    return false;
    +                }
    +            };
    +            let age = height.saturating_sub(tx_height);
    +            if age + 1 < COINBASE_MATURITY {
    +                return false;
    +            }
    +        }
    +
    +        true
    +    }
    +}
    +
    +// TOOD: make test
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/chain_graph.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/chain_graph.rs.html new file mode 100644 index 0000000000..31e986125e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/chain_graph.rs.html @@ -0,0 +1,1278 @@ +chain_graph.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +589
    +590
    +591
    +592
    +593
    +594
    +595
    +596
    +597
    +598
    +599
    +600
    +601
    +602
    +603
    +604
    +605
    +606
    +607
    +608
    +609
    +610
    +611
    +612
    +613
    +614
    +615
    +616
    +617
    +618
    +619
    +620
    +621
    +622
    +623
    +624
    +625
    +626
    +627
    +628
    +629
    +630
    +631
    +632
    +633
    +634
    +635
    +636
    +637
    +638
    +
    //! Module for structures that combine the features of [`sparse_chain`] and [`tx_graph`].
    +use crate::{
    +    collections::HashSet,
    +    sparse_chain::{self, ChainPosition, SparseChain},
    +    tx_graph::{self, TxGraph},
    +    BlockId, ForEachTxOut, FullTxOut, TxHeight,
    +};
    +use alloc::{string::ToString, vec::Vec};
    +use bitcoin::{OutPoint, Transaction, TxOut, Txid};
    +use core::fmt::Debug;
    +
    +/// A consistent combination of a [`SparseChain<P>`] and a [`TxGraph<T>`].
    +///
    +/// `SparseChain` only keeps track of transaction ids and their position in the chain but you often
    +/// want to store the full transactions as well. Additionally you want to make sure that everything
    +/// in the chain is consistent with the full transaction data. `ChainGraph` enforces these two
    +/// invariants:
    +///
    +/// 1. Every transaction that is in the chain is also in the graph (you always have the full
    +/// transaction).
    +/// 2. No transactions in the chain conflict with each other i.e. they don't double spend each
    +/// other or have ancestors that double spend each other.
    +///
    +/// Note that the `ChainGraph` guarantees a 1:1 mapping between transactions in the `chain` and
    +/// `graph` but not the other way around. Transactions may fall out of the *chain* (via re-org or
    +/// mempool eviction) but will remain in the *graph*.
    +#[derive(Clone, Debug, PartialEq)]
    +pub struct ChainGraph<P = TxHeight> {
    +    chain: SparseChain<P>,
    +    graph: TxGraph,
    +}
    +
    +impl<P> Default for ChainGraph<P> {
    +    fn default() -> Self {
    +        Self {
    +            chain: Default::default(),
    +            graph: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<P> AsRef<SparseChain<P>> for ChainGraph<P> {
    +    fn as_ref(&self) -> &SparseChain<P> {
    +        &self.chain
    +    }
    +}
    +
    +impl<P> AsRef<TxGraph> for ChainGraph<P> {
    +    fn as_ref(&self) -> &TxGraph {
    +        &self.graph
    +    }
    +}
    +
    +impl<P> AsRef<ChainGraph<P>> for ChainGraph<P> {
    +    fn as_ref(&self) -> &ChainGraph<P> {
    +        self
    +    }
    +}
    +
    +impl<P> ChainGraph<P> {
    +    /// Returns a reference to the internal [`SparseChain`].
    +    pub fn chain(&self) -> &SparseChain<P> {
    +        &self.chain
    +    }
    +
    +    /// Returns a reference to the internal [`TxGraph`].
    +    pub fn graph(&self) -> &TxGraph {
    +        &self.graph
    +    }
    +}
    +
    +impl<P> ChainGraph<P>
    +where
    +    P: ChainPosition,
    +{
    +    /// Create a new chain graph from a `chain` and a `graph`.
    +    ///
    +    /// There are two reasons this can return an `Err`:
    +    ///
    +    /// 1. There is a transaction in the `chain` that does not have its corresponding full
    +    /// transaction in `graph`.
    +    /// 2. The `chain` has two transactions that allegedly in it but they conflict in the `graph`
    +    /// (so could not possibly be in the same chain).
    +    pub fn new(chain: SparseChain<P>, graph: TxGraph) -> Result<Self, NewError<P>> {
    +        let mut missing = HashSet::default();
    +        for (pos, txid) in chain.txids() {
    +            if let Some(tx) = graph.get_tx(*txid) {
    +                let conflict = graph
    +                    .walk_conflicts(tx, |_, txid| Some((chain.tx_position(txid)?.clone(), txid)))
    +                    .next();
    +                if let Some((conflict_pos, conflict)) = conflict {
    +                    return Err(NewError::Conflict {
    +                        a: (pos.clone(), *txid),
    +                        b: (conflict_pos, conflict),
    +                    });
    +                }
    +            } else {
    +                missing.insert(*txid);
    +            }
    +        }
    +
    +        if !missing.is_empty() {
    +            return Err(NewError::Missing(missing));
    +        }
    +
    +        Ok(Self { chain, graph })
    +    }
    +
    +    /// Take an update in the form of a [`SparseChain<P>`][`SparseChain`] and attempt to turn it
    +    /// into a chain graph by filling in full transactions from `self` and from `new_txs`. This
    +    /// returns a `ChainGraph<P, Cow<T>>` where the [`Cow<'a, T>`] will borrow the transaction if it
    +    /// got it from `self`.
    +    ///
    +    /// This is useful when interacting with services like an electrum server which returns a list
    +    /// of txids and heights when calling [`script_get_history`] which can easily be inserted into a
    +    /// [`SparseChain<TxHeight>`][`SparseChain`]. From there you need to figure out which full
    +    /// transactions you are missing in your chain graph and form `new_txs`. You then use
    +    /// `inflate_update` to turn this into an update `ChainGraph<P, Cow<Transaction>>` and finally
    +    /// use [`determine_changeset`] to generate the changeset from it.
    +    ///
    +    /// [`SparseChain`]: crate::sparse_chain::SparseChain
    +    /// [`Cow<'a, T>`]: std::borrow::Cow
    +    /// [`script_get_history`]: https://docs.rs/electrum-client/latest/electrum_client/trait.ElectrumApi.html#tymethod.script_get_history
    +    /// [`determine_changeset`]: Self::determine_changeset
    +    pub fn inflate_update(
    +        &self,
    +        update: SparseChain<P>,
    +        new_txs: impl IntoIterator<Item = Transaction>,
    +    ) -> Result<ChainGraph<P>, NewError<P>> {
    +        let mut inflated_chain = SparseChain::default();
    +        let mut inflated_graph = TxGraph::default();
    +
    +        for (height, hash) in update.checkpoints().clone().into_iter() {
    +            let _ = inflated_chain
    +                .insert_checkpoint(BlockId { height, hash })
    +                .expect("must insert");
    +        }
    +
    +        // [TODO] @evanlinjin: These need better comments
    +        // - copy transactions that have changed positions into the graph
    +        // - add new transactions to inflated chain
    +        for (pos, txid) in update.txids() {
    +            match self.chain.tx_position(*txid) {
    +                Some(original_pos) => {
    +                    if original_pos != pos {
    +                        let tx = self
    +                            .graph
    +                            .get_tx(*txid)
    +                            .expect("tx must exist as it is referenced in sparsechain")
    +                            .clone();
    +                        let _ = inflated_chain
    +                            .insert_tx(*txid, pos.clone())
    +                            .expect("must insert since this was already in update");
    +                        let _ = inflated_graph.insert_tx(tx);
    +                    }
    +                }
    +                None => {
    +                    let _ = inflated_chain
    +                        .insert_tx(*txid, pos.clone())
    +                        .expect("must insert since this was already in update");
    +                }
    +            }
    +        }
    +
    +        for tx in new_txs {
    +            let _ = inflated_graph.insert_tx(tx);
    +        }
    +
    +        ChainGraph::new(inflated_chain, inflated_graph)
    +    }
    +
    +    /// Sets the checkpoint limit.
    +    ///
    +    /// Refer to [`SparseChain::checkpoint_limit`] for more.
    +    pub fn checkpoint_limit(&self) -> Option<usize> {
    +        self.chain.checkpoint_limit()
    +    }
    +
    +    /// Sets the checkpoint limit.
    +    ///
    +    /// Refer to [`SparseChain::set_checkpoint_limit`] for more.
    +    pub fn set_checkpoint_limit(&mut self, limit: Option<usize>) {
    +        self.chain.set_checkpoint_limit(limit)
    +    }
    +
    +    /// Determines the changes required to invalidate checkpoints `from_height` (inclusive) and
    +    /// above. Displaced transactions will have their positions moved to [`TxHeight::Unconfirmed`].
    +    pub fn invalidate_checkpoints_preview(&self, from_height: u32) -> ChangeSet<P> {
    +        ChangeSet {
    +            chain: self.chain.invalidate_checkpoints_preview(from_height),
    +            ..Default::default()
    +        }
    +    }
    +
    +    /// Invalidate checkpoints `from_height` (inclusive) and above. Displaced transactions will be
    +    /// re-positioned to [`TxHeight::Unconfirmed`].
    +    ///
    +    /// This is equivalent to calling [`Self::invalidate_checkpoints_preview`] and
    +    /// [`Self::apply_changeset`] in sequence.
    +    pub fn invalidate_checkpoints(&mut self, from_height: u32) -> ChangeSet<P>
    +    where
    +        ChangeSet<P>: Clone,
    +    {
    +        let changeset = self.invalidate_checkpoints_preview(from_height);
    +        self.apply_changeset(changeset.clone());
    +        changeset
    +    }
    +
    +    /// Get a transaction that is currently in the underlying [`SparseChain`].
    +    ///
    +    /// This does not necessarily mean that it is *confirmed* in the blockchain, it might just be in
    +    /// the unconfirmed transaction list within the [`SparseChain`].
    +    pub fn get_tx_in_chain(&self, txid: Txid) -> Option<(&P, &Transaction)> {
    +        let position = self.chain.tx_position(txid)?;
    +        let full_tx = self.graph.get_tx(txid).expect("must exist");
    +        Some((position, full_tx))
    +    }
    +
    +    /// Determines the changes required to insert a transaction into the inner [`ChainGraph`] and
    +    /// [`SparseChain`] at the given `position`.
    +    ///
    +    /// If inserting it into the chain `position` will result in conflicts, the returned
    +    /// [`ChangeSet`] should evict conflicting transactions.
    +    pub fn insert_tx_preview(
    +        &self,
    +        tx: Transaction,
    +        pos: P,
    +    ) -> Result<ChangeSet<P>, InsertTxError<P>> {
    +        let mut changeset = ChangeSet {
    +            chain: self.chain.insert_tx_preview(tx.txid(), pos)?,
    +            graph: self.graph.insert_tx_preview(tx),
    +        };
    +        self.fix_conflicts(&mut changeset)?;
    +        Ok(changeset)
    +    }
    +
    +    /// Inserts [`Transaction`] at given chain position.
    +    ///
    +    /// This is equivalent to calling [`Self::insert_tx_preview`] and [`Self::apply_changeset`] in
    +    /// sequence.
    +    pub fn insert_tx(&mut self, tx: Transaction, pos: P) -> Result<ChangeSet<P>, InsertTxError<P>> {
    +        let changeset = self.insert_tx_preview(tx, pos)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Determines the changes required to insert a [`TxOut`] into the internal [`TxGraph`].
    +    pub fn insert_txout_preview(&self, outpoint: OutPoint, txout: TxOut) -> ChangeSet<P> {
    +        ChangeSet {
    +            chain: Default::default(),
    +            graph: self.graph.insert_txout_preview(outpoint, txout),
    +        }
    +    }
    +
    +    /// Inserts a [`TxOut`] into the internal [`TxGraph`].
    +    ///
    +    /// This is equivalent to calling [`Self::insert_txout_preview`] and [`Self::apply_changeset`]
    +    /// in sequence.
    +    pub fn insert_txout(&mut self, outpoint: OutPoint, txout: TxOut) -> ChangeSet<P> {
    +        let changeset = self.insert_txout_preview(outpoint, txout);
    +        self.apply_changeset(changeset.clone());
    +        changeset
    +    }
    +
    +    /// Determines the changes required to insert a `block_id` (a height and block hash) into the
    +    /// chain.
    +    ///
    +    /// If a checkpoint already exists at that height with a different hash this will return
    +    /// an error.
    +    pub fn insert_checkpoint_preview(
    +        &self,
    +        block_id: BlockId,
    +    ) -> Result<ChangeSet<P>, InsertCheckpointError> {
    +        self.chain
    +            .insert_checkpoint_preview(block_id)
    +            .map(|chain_changeset| ChangeSet {
    +                chain: chain_changeset,
    +                ..Default::default()
    +            })
    +    }
    +
    +    /// Inserts checkpoint into [`Self`].
    +    ///
    +    /// This is equivalent to calling [`Self::insert_checkpoint_preview`] and
    +    /// [`Self::apply_changeset`] in sequence.
    +    pub fn insert_checkpoint(
    +        &mut self,
    +        block_id: BlockId,
    +    ) -> Result<ChangeSet<P>, InsertCheckpointError> {
    +        let changeset = self.insert_checkpoint_preview(block_id)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Calculates the difference between self and `update` in the form of a [`ChangeSet`].
    +    pub fn determine_changeset(
    +        &self,
    +        update: &ChainGraph<P>,
    +    ) -> Result<ChangeSet<P>, UpdateError<P>> {
    +        let chain_changeset = self
    +            .chain
    +            .determine_changeset(&update.chain)
    +            .map_err(UpdateError::Chain)?;
    +
    +        let mut changeset = ChangeSet {
    +            chain: chain_changeset,
    +            graph: self.graph.determine_additions(&update.graph),
    +        };
    +
    +        self.fix_conflicts(&mut changeset)?;
    +        Ok(changeset)
    +    }
    +
    +    /// Given a transaction, return an iterator of `txid`s that conflict with it (spends at least
    +    /// one of the same inputs). This includes all descendants of conflicting transactions.
    +    ///
    +    /// This method only returns conflicts that exist in the [`SparseChain`] as transactions that
    +    /// are not included in [`SparseChain`] are already considered as evicted.
    +    pub fn tx_conflicts_in_chain<'a>(
    +        &'a self,
    +        tx: &'a Transaction,
    +    ) -> impl Iterator<Item = (&'a P, Txid)> + 'a {
    +        self.graph.walk_conflicts(tx, move |_, conflict_txid| {
    +            self.chain
    +                .tx_position(conflict_txid)
    +                .map(|conflict_pos| (conflict_pos, conflict_txid))
    +        })
    +    }
    +
    +    /// Fix changeset conflicts.
    +    ///
    +    /// **WARNING:** If there are any missing full txs, conflict resolution will not be complete. In
    +    /// debug mode, this will result in panic.
    +    fn fix_conflicts(&self, changeset: &mut ChangeSet<P>) -> Result<(), UnresolvableConflict<P>> {
    +        let mut chain_conflicts = vec![];
    +
    +        for (&txid, pos_change) in &changeset.chain.txids {
    +            let pos = match pos_change {
    +                Some(pos) => {
    +                    // Ignore txs that are still in the chain -- we only care about new ones
    +                    if self.chain.tx_position(txid).is_some() {
    +                        continue;
    +                    }
    +                    pos
    +                }
    +                // Ignore txids that are being delted by the change (they can't conflict)
    +                None => continue,
    +            };
    +
    +            let mut full_tx = self.graph.get_tx(txid);
    +
    +            if full_tx.is_none() {
    +                full_tx = changeset.graph.tx.iter().find(|tx| tx.txid() == txid)
    +            }
    +
    +            debug_assert!(full_tx.is_some(), "should have full tx at this point");
    +
    +            let full_tx = match full_tx {
    +                Some(full_tx) => full_tx,
    +                None => continue,
    +            };
    +
    +            for (conflict_pos, conflict_txid) in self.tx_conflicts_in_chain(full_tx) {
    +                chain_conflicts.push((pos.clone(), txid, conflict_pos, conflict_txid))
    +            }
    +        }
    +
    +        for (update_pos, update_txid, conflicting_pos, conflicting_txid) in chain_conflicts {
    +            // We have found a tx that conflicts with our update txid. Only allow this when the
    +            // conflicting tx will be positioned as "unconfirmed" after the update is applied.
    +            // If so, we will modify the changeset to evict the conflicting txid.
    +
    +            // determine the position of the conflicting txid after current changeset is applied
    +            let conflicting_new_pos = changeset
    +                .chain
    +                .txids
    +                .get(&conflicting_txid)
    +                .map(Option::as_ref)
    +                .unwrap_or(Some(conflicting_pos));
    +
    +            match conflicting_new_pos {
    +                None => {
    +                    // conflicting txid will be deleted, can ignore
    +                }
    +                Some(existing_new_pos) => match existing_new_pos.height() {
    +                    TxHeight::Confirmed(_) => {
    +                        // the new postion of the conflicting tx is "confirmed", therefore cannot be
    +                        // evicted, return error
    +                        return Err(UnresolvableConflict {
    +                            already_confirmed_tx: (conflicting_pos.clone(), conflicting_txid),
    +                            update_tx: (update_pos, update_txid),
    +                        });
    +                    }
    +                    TxHeight::Unconfirmed => {
    +                        // the new position of the conflicting tx is "unconfirmed", therefore it can
    +                        // be evicted
    +                        changeset.chain.txids.insert(conflicting_txid, None);
    +                    }
    +                },
    +            };
    +        }
    +
    +        Ok(())
    +    }
    +
    +    /// Applies `changeset` to `self`.
    +    ///
    +    /// **Warning** this method assumes the changeset is assumed to be correctly formed. If it isn't
    +    /// then the chain graph may not behave correctly in the future and may panic unexpectedly.
    +    pub fn apply_changeset(&mut self, changeset: ChangeSet<P>) {
    +        self.chain.apply_changeset(changeset.chain);
    +        self.graph.apply_additions(changeset.graph);
    +    }
    +
    +    /// Applies the `update` chain graph. Note this is shorthand for calling
    +    /// [`Self::determine_changeset()`] and [`Self::apply_changeset()`] in sequence.
    +    pub fn apply_update(&mut self, update: ChainGraph<P>) -> Result<ChangeSet<P>, UpdateError<P>> {
    +        let changeset = self.determine_changeset(&update)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Get the full transaction output at an outpoint if it exists in the chain and the graph.
    +    pub fn full_txout(&self, outpoint: OutPoint) -> Option<FullTxOut<P>> {
    +        self.chain.full_txout(&self.graph, outpoint)
    +    }
    +
    +    /// Iterate over the full transactions and their position in the chain ordered by their position
    +    /// in ascending order.
    +    pub fn transactions_in_chain(&self) -> impl DoubleEndedIterator<Item = (&P, &Transaction)> {
    +        self.chain
    +            .txids()
    +            .map(move |(pos, txid)| (pos, self.graph.get_tx(*txid).expect("must exist")))
    +    }
    +
    +    /// Finds the transaction in the chain that spends `outpoint` given the input/output
    +    /// relationships in `graph`. Note that the transaction including `outpoint` does not need to be
    +    /// in the `graph` or the `chain` for this to return `Some(_)`.
    +    pub fn spent_by(&self, outpoint: OutPoint) -> Option<(&P, Txid)> {
    +        self.chain.spent_by(&self.graph, outpoint)
    +    }
    +
    +    /// Whether the chain graph contains any data whatsoever.
    +    pub fn is_empty(&self) -> bool {
    +        self.chain.is_empty() && self.graph.is_empty()
    +    }
    +}
    +
    +/// Represents changes to [`ChainGraph`].
    +///
    +/// This is essentially a combination of [`sparse_chain::ChangeSet`] and [`tx_graph::Additions`].
    +#[derive(Debug, Clone, PartialEq)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(
    +        crate = "serde_crate",
    +        bound(
    +            deserialize = "P: serde::Deserialize<'de>",
    +            serialize = "P: serde::Serialize"
    +        )
    +    )
    +)]
    +#[must_use]
    +pub struct ChangeSet<P> {
    +    pub chain: sparse_chain::ChangeSet<P>,
    +    pub graph: tx_graph::Additions,
    +}
    +
    +impl<P> ChangeSet<P> {
    +    /// Returns `true` if this [`ChangeSet`] records no changes.
    +    pub fn is_empty(&self) -> bool {
    +        self.chain.is_empty() && self.graph.is_empty()
    +    }
    +
    +    /// Returns `true` if this [`ChangeSet`] contains transaction evictions.
    +    pub fn contains_eviction(&self) -> bool {
    +        self.chain
    +            .txids
    +            .iter()
    +            .any(|(_, new_pos)| new_pos.is_none())
    +    }
    +
    +    /// Appends the changes in `other` into self such that applying `self` afterwards has the same
    +    /// effect as sequentially applying the original `self` and `other`.
    +    pub fn append(&mut self, other: ChangeSet<P>)
    +    where
    +        P: ChainPosition,
    +    {
    +        self.chain.append(other.chain);
    +        self.graph.append(other.graph);
    +    }
    +}
    +
    +impl<P> Default for ChangeSet<P> {
    +    fn default() -> Self {
    +        Self {
    +            chain: Default::default(),
    +            graph: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<P> ForEachTxOut for ChainGraph<P> {
    +    fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut))) {
    +        self.graph.for_each_txout(f)
    +    }
    +}
    +
    +impl<P> ForEachTxOut for ChangeSet<P> {
    +    fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut))) {
    +        self.graph.for_each_txout(f)
    +    }
    +}
    +
    +/// Error that may occur when calling [`ChainGraph::new`].
    +#[derive(Clone, Debug, PartialEq)]
    +pub enum NewError<P> {
    +    /// Two transactions within the sparse chain conflicted with each other
    +    Conflict { a: (P, Txid), b: (P, Txid) },
    +    /// One or more transactions in the chain were not in the graph
    +    Missing(HashSet<Txid>),
    +}
    +
    +impl<P: core::fmt::Debug> core::fmt::Display for NewError<P> {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            NewError::Conflict { a, b } => write!(
    +                f,
    +                "Unable to inflate sparse chain to chain graph since transactions {:?} and {:?}",
    +                a, b
    +            ),
    +            NewError::Missing(missing) => write!(
    +                f,
    +                "missing full transactions for {}",
    +                missing
    +                    .iter()
    +                    .map(|txid| txid.to_string())
    +                    .collect::<Vec<_>>()
    +                    .join(", ")
    +            ),
    +        }
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl<P: core::fmt::Debug> std::error::Error for NewError<P> {}
    +
    +/// Error that may occur when inserting a transaction.
    +///
    +/// Refer to [`ChainGraph::insert_tx_preview`] and [`ChainGraph::insert_tx`].
    +#[derive(Clone, Debug, PartialEq)]
    +pub enum InsertTxError<P> {
    +    Chain(sparse_chain::InsertTxError<P>),
    +    UnresolvableConflict(UnresolvableConflict<P>),
    +}
    +
    +impl<P: core::fmt::Debug> core::fmt::Display for InsertTxError<P> {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            InsertTxError::Chain(inner) => core::fmt::Display::fmt(inner, f),
    +            InsertTxError::UnresolvableConflict(inner) => core::fmt::Display::fmt(inner, f),
    +        }
    +    }
    +}
    +
    +impl<P> From<sparse_chain::InsertTxError<P>> for InsertTxError<P> {
    +    fn from(inner: sparse_chain::InsertTxError<P>) -> Self {
    +        Self::Chain(inner)
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl<P: core::fmt::Debug> std::error::Error for InsertTxError<P> {}
    +
    +/// A nice alias of [`sparse_chain::InsertCheckpointError`].
    +pub type InsertCheckpointError = sparse_chain::InsertCheckpointError;
    +
    +/// Represents an update failure.
    +#[derive(Clone, Debug, PartialEq)]
    +pub enum UpdateError<P> {
    +    /// The update chain was inconsistent with the existing chain
    +    Chain(sparse_chain::UpdateError<P>),
    +    /// A transaction in the update spent the same input as an already confirmed transaction
    +    UnresolvableConflict(UnresolvableConflict<P>),
    +}
    +
    +impl<P: core::fmt::Debug> core::fmt::Display for UpdateError<P> {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            UpdateError::Chain(inner) => core::fmt::Display::fmt(inner, f),
    +            UpdateError::UnresolvableConflict(inner) => core::fmt::Display::fmt(inner, f),
    +        }
    +    }
    +}
    +
    +impl<P> From<sparse_chain::UpdateError<P>> for UpdateError<P> {
    +    fn from(inner: sparse_chain::UpdateError<P>) -> Self {
    +        Self::Chain(inner)
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl<P: core::fmt::Debug> std::error::Error for UpdateError<P> {}
    +
    +/// Represents an unresolvable conflict between an update's transaction and an
    +/// already-confirmed transaction.
    +#[derive(Clone, Debug, PartialEq)]
    +pub struct UnresolvableConflict<P> {
    +    pub already_confirmed_tx: (P, Txid),
    +    pub update_tx: (P, Txid),
    +}
    +
    +impl<P: core::fmt::Debug> core::fmt::Display for UnresolvableConflict<P> {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        let Self {
    +            already_confirmed_tx,
    +            update_tx,
    +        } = self;
    +        write!(f, "update transaction {} at height {:?} conflicts with an already confirmed transaction {} at height {:?}",
    +            update_tx.1, update_tx.0, already_confirmed_tx.1, already_confirmed_tx.0)
    +    }
    +}
    +
    +impl<P> From<UnresolvableConflict<P>> for UpdateError<P> {
    +    fn from(inner: UnresolvableConflict<P>) -> Self {
    +        Self::UnresolvableConflict(inner)
    +    }
    +}
    +
    +impl<P> From<UnresolvableConflict<P>> for InsertTxError<P> {
    +    fn from(inner: UnresolvableConflict<P>) -> Self {
    +        Self::UnresolvableConflict(inner)
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl<P: core::fmt::Debug> std::error::Error for UnresolvableConflict<P> {}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/descriptor_ext.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/descriptor_ext.rs.html new file mode 100644 index 0000000000..4843aea1be --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/descriptor_ext.rs.html @@ -0,0 +1,34 @@ +descriptor_ext.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +
    use crate::miniscript::{Descriptor, DescriptorPublicKey};
    +
    +/// A trait to extend the functionality of a miniscript descriptor.
    +pub trait DescriptorExt {
    +    /// Returns the minimum value (in satoshis) that an output should have to be broadcastable.
    +    fn dust_value(&self) -> u64;
    +}
    +
    +impl DescriptorExt for Descriptor<DescriptorPublicKey> {
    +    fn dust_value(&self) -> u64 {
    +        self.at_derivation_index(0)
    +            .script_pubkey()
    +            .dust_value()
    +            .to_sat()
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/example_utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/example_utils.rs.html new file mode 100644 index 0000000000..2f323d0436 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/example_utils.rs.html @@ -0,0 +1,62 @@ +example_utils.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +
    #![allow(unused)]
    +use alloc::vec::Vec;
    +use bitcoin::{
    +    consensus,
    +    hashes::{hex::FromHex, Hash},
    +    Transaction,
    +};
    +
    +use crate::BlockId;
    +
    +pub const RAW_TX_1: &str = "0200000000010116d6174da7183d70d0a7d4dc314d517a7d135db79ad63515028b293a76f4f9d10000000000feffffff023a21fc8350060000160014531c405e1881ef192294b8813631e258bf98ea7a1027000000000000225120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c024730440220591b1a172a122da49ba79a3e79f98aaa03fd7a372f9760da18890b6a327e6010022013e82319231da6c99abf8123d7c07e13cf9bd8d76e113e18dc452e5024db156d012102318a2d558b2936c52e320decd6d92a88d7f530be91b6fe0af5caf41661e77da3ef2e0100";
    +pub const RAW_TX_2: &str = "02000000000101a688607020cfae91a61e7c516b5ef1264d5d77f17200c3866826c6c808ebf1620000000000feffffff021027000000000000225120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c20fd48ff530600001600146886c525e41d4522042bd0b159dfbade2504a6bb024730440220740ff7e665cd20565d4296b549df8d26b941be3f1e3af89a0b60e50c0dbeb69a02206213ab7030cf6edc6c90d4ccf33010644261e029950a688dc0b1a9ebe6ddcc5a012102f2ac6b396a97853cb6cd62242c8ae4842024742074475023532a51e9c53194253e760100";
    +pub const RAW_TX_3: &str = "0200000000010135d67ee47b557e68b8c6223958f597381965ed719f1207ee2b9e20432a24a5dc0100000000feffffff021027000000000000225120a82f29944d65b86ae6b5e5cc75e294ead6c59391a1edc5e016e3498c67fc7bbb62215a5055060000160014070df7671dea67a50c4799a744b5c9be8f4bac690247304402207ebf8d29f71fd03e7e6977b3ea78ca5fcc5c49a42ae822348fc401862fdd766c02201d7e4ff0684ecb008b6142f36ead1b0b4d615524c4f58c261113d361f4427e25012103e6a75e2fab85e5ecad641afc4ffba7222f998649d9f18cac92f0fcc8618883b3ee760100";
    +pub const RAW_TX_4: &str = "02000000000101d00e8f76ed313e19b339ee293c0f52b0325c95e24c8f3966fa353fb2bedbcf580100000000feffffff021027000000000000225120882d74e5d0572d5a816cef0041a96b6c1de832f6f9676d9605c44d5e9a97d3dc9cda55fe53060000160014852b5864b8edd42fab4060c87f818e50780865ff0247304402201dccbb9bed7fba924b6d249c5837cc9b37470c0e3d8fbea77cb59baba3efe6fa0220700cc170916913b9bfc2bc0fefb6af776e8b542c561702f136cddc1c7aa43141012103acec3fc79dbbca745815c2a807dc4e81010c80e308e84913f59cb42a275dad97f3760100";
    +
    +pub fn tx_from_hex(s: &str) -> Transaction {
    +    let raw = Vec::from_hex(s).expect("data must be in hex");
    +    consensus::deserialize(raw.as_slice()).expect("must deserialize")
    +}
    +
    +pub fn new_hash<H: Hash>(s: &str) -> H {
    +    <H as bitcoin::hashes::Hash>::hash(s.as_bytes())
    +}
    +
    +pub fn new_block_id(height: u32, hash: &str) -> BlockId {
    +    BlockId {
    +        height,
    +        hash: new_hash(hash),
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain.rs.html new file mode 100644 index 0000000000..9865f26fe9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain.rs.html @@ -0,0 +1,620 @@ +keychain.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +
    //! Module for keychain based structures.
    +//!
    +//! A keychain here is a set of application defined indexes for a minscript descriptor where we can
    +//! derive script pubkeys at a particular derivation index. The application's index is simply
    +//! anything that implements `Ord`.
    +//!
    +//! [`KeychainTxOutIndex`] indexes script pubkeys of keychains and scans in relevant outpoints (that
    +//! has a `txout` containing an indexed script pubkey). Internally, this uses [`SpkTxOutIndex`], but
    +//! also maintains "revealed" and "lookahead" index count per keychain.
    +//!
    +//! [`KeychainTracker`] combines [`ChainGraph`] and [`KeychainTxOutIndex`] and enforces atomic
    +//! changes between both these structures. [`KeychainScan`] is a structure used to update to
    +//! [`KeychainTracker`] and changes made on a [`KeychainTracker`] are reported by
    +//! [`KeychainChangeSet`]s.
    +//!
    +//! [`SpkTxOutIndex`]: crate::SpkTxOutIndex
    +use crate::{
    +    chain_graph::{self, ChainGraph},
    +    collections::BTreeMap,
    +    sparse_chain::ChainPosition,
    +    tx_graph::TxGraph,
    +    ForEachTxOut,
    +};
    +
    +#[cfg(feature = "miniscript")]
    +pub mod persist;
    +#[cfg(feature = "miniscript")]
    +pub use persist::*;
    +#[cfg(feature = "miniscript")]
    +mod tracker;
    +#[cfg(feature = "miniscript")]
    +pub use tracker::*;
    +#[cfg(feature = "miniscript")]
    +mod txout_index;
    +#[cfg(feature = "miniscript")]
    +pub use txout_index::*;
    +
    +/// Represents updates to the derivation index of a [`KeychainTxOutIndex`].
    +///
    +/// It can be applied to [`KeychainTxOutIndex`] with [`apply_additions`]. [`DerivationAdditions] are
    +/// monotone in that they will never decrease the revealed derivation index.
    +///
    +/// [`KeychainTxOutIndex`]: crate::keychain::KeychainTxOutIndex
    +/// [`apply_additions`]: crate::keychain::KeychainTxOutIndex::apply_additions
    +#[derive(Clone, Debug, PartialEq)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(
    +        crate = "serde_crate",
    +        bound(
    +            deserialize = "K: Ord + serde::Deserialize<'de>",
    +            serialize = "K: Ord + serde::Serialize"
    +        )
    +    )
    +)]
    +#[must_use]
    +pub struct DerivationAdditions<K>(pub BTreeMap<K, u32>);
    +
    +impl<K> DerivationAdditions<K> {
    +    /// Returns whether the additions are empty.
    +    pub fn is_empty(&self) -> bool {
    +        self.0.is_empty()
    +    }
    +
    +    /// Get the inner map of keychain to its new derivation index.
    +    pub fn as_inner(&self) -> &BTreeMap<K, u32> {
    +        &self.0
    +    }
    +}
    +
    +impl<K: Ord> DerivationAdditions<K> {
    +    /// Append another [`DerivationAdditions`] into self.
    +    ///
    +    /// If keychain already exists, increases the index when other's index > self's index.
    +    /// If keychain did not exist, append the new keychain.
    +    pub fn append(&mut self, mut other: Self) {
    +        self.0.iter_mut().for_each(|(key, index)| {
    +            if let Some(other_index) = other.0.remove(key) {
    +                *index = other_index.max(*index);
    +            }
    +        });
    +
    +        self.0.append(&mut other.0);
    +    }
    +}
    +
    +impl<K> Default for DerivationAdditions<K> {
    +    fn default() -> Self {
    +        Self(Default::default())
    +    }
    +}
    +
    +impl<K> AsRef<BTreeMap<K, u32>> for DerivationAdditions<K> {
    +    fn as_ref(&self) -> &BTreeMap<K, u32> {
    +        &self.0
    +    }
    +}
    +
    +#[derive(Clone, Debug, PartialEq)]
    +/// An update that includes the last active indexes of each keychain.
    +pub struct KeychainScan<K, P> {
    +    /// The update data in the form of a chain that could be applied
    +    pub update: ChainGraph<P>,
    +    /// The last active indexes of each keychain
    +    pub last_active_indices: BTreeMap<K, u32>,
    +}
    +
    +impl<K, P> Default for KeychainScan<K, P> {
    +    fn default() -> Self {
    +        Self {
    +            update: Default::default(),
    +            last_active_indices: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<K, P> From<ChainGraph<P>> for KeychainScan<K, P> {
    +    fn from(update: ChainGraph<P>) -> Self {
    +        KeychainScan {
    +            update,
    +            last_active_indices: Default::default(),
    +        }
    +    }
    +}
    +
    +/// Represents changes to a [`KeychainTracker`].
    +///
    +/// This is essentially a combination of [`DerivationAdditions`] and [`chain_graph::ChangeSet`].
    +#[derive(Clone, Debug)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(
    +        crate = "serde_crate",
    +        bound(
    +            deserialize = "K: Ord + serde::Deserialize<'de>, P: serde::Deserialize<'de>",
    +            serialize = "K: Ord + serde::Serialize, P: serde::Serialize"
    +        )
    +    )
    +)]
    +#[must_use]
    +pub struct KeychainChangeSet<K, P> {
    +    /// The changes in local keychain derivation indices
    +    pub derivation_indices: DerivationAdditions<K>,
    +    /// The changes that have occurred in the blockchain
    +    pub chain_graph: chain_graph::ChangeSet<P>,
    +}
    +
    +impl<K, P> Default for KeychainChangeSet<K, P> {
    +    fn default() -> Self {
    +        Self {
    +            chain_graph: Default::default(),
    +            derivation_indices: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<K, P> KeychainChangeSet<K, P> {
    +    /// Returns whether the [`KeychainChangeSet`] is empty (no changes recorded).
    +    pub fn is_empty(&self) -> bool {
    +        self.chain_graph.is_empty() && self.derivation_indices.is_empty()
    +    }
    +
    +    /// Appends the changes in `other` into `self` such that applying `self` afterwards has the same
    +    /// effect as sequentially applying the original `self` and `other`.
    +    ///
    +    /// Note the derivation indices cannot be decreased so `other` will only change the derivation
    +    /// index for a keychain if it's entry is higher than the one in `self`.
    +    pub fn append(&mut self, other: KeychainChangeSet<K, P>)
    +    where
    +        K: Ord,
    +        P: ChainPosition,
    +    {
    +        self.derivation_indices.append(other.derivation_indices);
    +        self.chain_graph.append(other.chain_graph);
    +    }
    +}
    +
    +impl<K, P> From<chain_graph::ChangeSet<P>> for KeychainChangeSet<K, P> {
    +    fn from(changeset: chain_graph::ChangeSet<P>) -> Self {
    +        Self {
    +            chain_graph: changeset,
    +            ..Default::default()
    +        }
    +    }
    +}
    +
    +impl<K, P> From<DerivationAdditions<K>> for KeychainChangeSet<K, P> {
    +    fn from(additions: DerivationAdditions<K>) -> Self {
    +        Self {
    +            derivation_indices: additions,
    +            ..Default::default()
    +        }
    +    }
    +}
    +
    +impl<K, P> AsRef<TxGraph> for KeychainScan<K, P> {
    +    fn as_ref(&self) -> &TxGraph {
    +        self.update.graph()
    +    }
    +}
    +
    +impl<K, P> ForEachTxOut for KeychainChangeSet<K, P> {
    +    fn for_each_txout(&self, f: impl FnMut((bitcoin::OutPoint, &bitcoin::TxOut))) {
    +        self.chain_graph.for_each_txout(f)
    +    }
    +}
    +
    +/// Balance differentiated in various categories.
    +#[derive(Debug, PartialEq, Eq, Clone, Default)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(crate = "serde_crate",)
    +)]
    +pub struct Balance {
    +    /// All coinbase outputs not yet matured
    +    pub immature: u64,
    +    /// Unconfirmed UTXOs generated by a wallet tx
    +    pub trusted_pending: u64,
    +    /// Unconfirmed UTXOs received from an external wallet
    +    pub untrusted_pending: u64,
    +    /// Confirmed and immediately spendable balance
    +    pub confirmed: u64,
    +}
    +
    +impl Balance {
    +    /// Get sum of trusted_pending and confirmed coins.
    +    ///
    +    /// This is the balance you can spend right now that shouldn't get cancelled via another party
    +    /// double spending it.
    +    pub fn trusted_spendable(&self) -> u64 {
    +        self.confirmed + self.trusted_pending
    +    }
    +
    +    /// Get the whole balance visible to the wallet.
    +    pub fn total(&self) -> u64 {
    +        self.confirmed + self.trusted_pending + self.untrusted_pending + self.immature
    +    }
    +}
    +
    +impl core::fmt::Display for Balance {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        write!(
    +            f,
    +            "{{ immature: {}, trusted_pending: {}, untrusted_pending: {}, confirmed: {} }}",
    +            self.immature, self.trusted_pending, self.untrusted_pending, self.confirmed
    +        )
    +    }
    +}
    +
    +impl core::ops::Add for Balance {
    +    type Output = Self;
    +
    +    fn add(self, other: Self) -> Self {
    +        Self {
    +            immature: self.immature + other.immature,
    +            trusted_pending: self.trusted_pending + other.trusted_pending,
    +            untrusted_pending: self.untrusted_pending + other.untrusted_pending,
    +            confirmed: self.confirmed + other.confirmed,
    +        }
    +    }
    +}
    +
    +#[cfg(test)]
    +mod test {
    +    use crate::TxHeight;
    +
    +    use super::*;
    +    #[test]
    +    fn append_keychain_derivation_indices() {
    +        #[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
    +        enum Keychain {
    +            One,
    +            Two,
    +            Three,
    +            Four,
    +        }
    +        let mut lhs_di = BTreeMap::<Keychain, u32>::default();
    +        let mut rhs_di = BTreeMap::<Keychain, u32>::default();
    +        lhs_di.insert(Keychain::One, 7);
    +        lhs_di.insert(Keychain::Two, 0);
    +        rhs_di.insert(Keychain::One, 3);
    +        rhs_di.insert(Keychain::Two, 5);
    +        lhs_di.insert(Keychain::Three, 3);
    +        rhs_di.insert(Keychain::Four, 4);
    +        let mut lhs = KeychainChangeSet {
    +            derivation_indices: DerivationAdditions(lhs_di),
    +            chain_graph: chain_graph::ChangeSet::<TxHeight>::default(),
    +        };
    +
    +        let rhs = KeychainChangeSet {
    +            derivation_indices: DerivationAdditions(rhs_di),
    +            chain_graph: chain_graph::ChangeSet::<TxHeight>::default(),
    +        };
    +
    +        lhs.append(rhs);
    +
    +        // Exiting index doesn't update if new index in `other` is lower than `self`
    +        assert_eq!(lhs.derivation_indices.0.get(&Keychain::One), Some(&7));
    +        // Existing index updates if new index in `other` is higher than `self.
    +        assert_eq!(lhs.derivation_indices.0.get(&Keychain::Two), Some(&5));
    +        // Existing index unchanged, if keychain doesn't exist in `other`
    +        assert_eq!(lhs.derivation_indices.0.get(&Keychain::Three), Some(&3));
    +        // New keychain gets added if keychain is in `other`, but not in `self`.
    +        assert_eq!(lhs.derivation_indices.0.get(&Keychain::Four), Some(&4));
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/persist.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/persist.rs.html new file mode 100644 index 0000000000..ea255b252e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/persist.rs.html @@ -0,0 +1,218 @@ +persist.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +
    //! Persistence for changes made to a [`KeychainTracker`].
    +//!
    +//! BDK's [`KeychainTracker`] needs somewhere to persist changes it makes during operation.
    +//! Operations like giving out a new address are crucial to persist so that next time the
    +//! application is loaded it can find transactions related to that address.
    +//!
    +//! Note that the [`KeychainTracker`] does not read this persisted data during operation since it
    +//! always has a copy in memory.
    +//!
    +//! [`KeychainTracker`]: crate::keychain::KeychainTracker
    +
    +use crate::{keychain, sparse_chain::ChainPosition};
    +
    +/// `Persist` wraps a [`PersistBackend`] to create a convenient staging area for changes before they
    +/// are persisted. Not all changes made to the [`KeychainTracker`] need to be written to disk right
    +/// away so you can use [`Persist::stage`] to *stage* it first and then [`Persist::commit`] to
    +/// finally write it to disk.
    +///
    +/// [`KeychainTracker`]: keychain::KeychainTracker
    +#[derive(Debug)]
    +pub struct Persist<K, P, B> {
    +    backend: B,
    +    stage: keychain::KeychainChangeSet<K, P>,
    +}
    +
    +impl<K, P, B> Persist<K, P, B> {
    +    /// Create a new `Persist` from a [`PersistBackend`].
    +    pub fn new(backend: B) -> Self {
    +        Self {
    +            backend,
    +            stage: Default::default(),
    +        }
    +    }
    +
    +    /// Stage a `changeset` to later persistence with [`commit`].
    +    ///
    +    /// [`commit`]: Self::commit
    +    pub fn stage(&mut self, changeset: keychain::KeychainChangeSet<K, P>)
    +    where
    +        K: Ord,
    +        P: ChainPosition,
    +    {
    +        self.stage.append(changeset)
    +    }
    +
    +    /// Get the changes that haven't been commited yet
    +    pub fn staged(&self) -> &keychain::KeychainChangeSet<K, P> {
    +        &self.stage
    +    }
    +
    +    /// Commit the staged changes to the underlying persistence backend.
    +    ///
    +    /// Retuns a backend defined error if this fails
    +    pub fn commit(&mut self) -> Result<(), B::WriteError>
    +    where
    +        B: PersistBackend<K, P>,
    +    {
    +        self.backend.append_changeset(&self.stage)?;
    +        self.stage = Default::default();
    +        Ok(())
    +    }
    +}
    +
    +/// A persistence backend for [`Persist`].
    +pub trait PersistBackend<K, P> {
    +    /// The error the backend returns when it fails to write.
    +    type WriteError: core::fmt::Debug;
    +
    +    /// The error the backend returns when it fails to load.
    +    type LoadError: core::fmt::Debug;
    +
    +    /// Appends a new changeset to the persistance backend.
    +    ///
    +    /// It is up to the backend what it does with this. It could store every changeset in a list or
    +    /// it insert the actual changes to a more structured database. All it needs to guarantee is
    +    /// that [`load_into_keychain_tracker`] restores a keychain tracker to what it should be if all
    +    /// changesets had been applied sequentially.
    +    ///
    +    /// [`load_into_keychain_tracker`]: Self::load_into_keychain_tracker
    +    fn append_changeset(
    +        &mut self,
    +        changeset: &keychain::KeychainChangeSet<K, P>,
    +    ) -> Result<(), Self::WriteError>;
    +
    +    /// Applies all the changesets the backend has received to `tracker`.
    +    fn load_into_keychain_tracker(
    +        &mut self,
    +        tracker: &mut keychain::KeychainTracker<K, P>,
    +    ) -> Result<(), Self::LoadError>;
    +}
    +
    +impl<K, P> PersistBackend<K, P> for () {
    +    type WriteError = ();
    +    type LoadError = ();
    +
    +    fn append_changeset(
    +        &mut self,
    +        _changeset: &keychain::KeychainChangeSet<K, P>,
    +    ) -> Result<(), Self::WriteError> {
    +        Ok(())
    +    }
    +    fn load_into_keychain_tracker(
    +        &mut self,
    +        _tracker: &mut keychain::KeychainTracker<K, P>,
    +    ) -> Result<(), Self::LoadError> {
    +        Ok(())
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/tracker.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/tracker.rs.html new file mode 100644 index 0000000000..c96c5d07d2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/tracker.rs.html @@ -0,0 +1,618 @@ +tracker.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +
    use bitcoin::Transaction;
    +use miniscript::{Descriptor, DescriptorPublicKey};
    +
    +use crate::{
    +    chain_graph::{self, ChainGraph},
    +    collections::*,
    +    keychain::{KeychainChangeSet, KeychainScan, KeychainTxOutIndex},
    +    sparse_chain::{self, SparseChain},
    +    tx_graph::TxGraph,
    +    BlockId, FullTxOut, TxHeight,
    +};
    +
    +use super::{Balance, DerivationAdditions};
    +
    +/// A convenient combination of a [`KeychainTxOutIndex`] and a [`ChainGraph`].
    +///
    +/// The [`KeychainTracker`] atomically updates its [`KeychainTxOutIndex`] whenever new chain data is
    +/// incorporated into its internal [`ChainGraph`].
    +#[derive(Clone, Debug)]
    +pub struct KeychainTracker<K, P> {
    +    /// Index between script pubkeys to transaction outputs
    +    pub txout_index: KeychainTxOutIndex<K>,
    +    chain_graph: ChainGraph<P>,
    +}
    +
    +impl<K, P> KeychainTracker<K, P>
    +where
    +    P: sparse_chain::ChainPosition,
    +    K: Ord + Clone + core::fmt::Debug,
    +{
    +    /// Add a keychain to the tracker's `txout_index` with a descriptor to derive addresses for it.
    +    /// This is just shorthand for calling [`KeychainTxOutIndex::add_keychain`] on the internal
    +    /// `txout_index`.
    +    ///
    +    /// Adding a keychain means you will be able to derive new script pubkeys under that keychain
    +    /// and the tracker will discover transaction outputs with those script pubkeys.
    +    pub fn add_keychain(&mut self, keychain: K, descriptor: Descriptor<DescriptorPublicKey>) {
    +        self.txout_index.add_keychain(keychain, descriptor)
    +    }
    +
    +    /// Get the internal map of keychains to their descriptors. This is just shorthand for calling
    +    /// [`KeychainTxOutIndex::keychains`] on the internal `txout_index`.
    +    pub fn keychains(&mut self) -> &BTreeMap<K, Descriptor<DescriptorPublicKey>> {
    +        self.txout_index.keychains()
    +    }
    +
    +    /// Get the checkpoint limit of the internal [`SparseChain`].
    +    ///
    +    /// Refer to [`SparseChain::checkpoint_limit`] for more.
    +    pub fn checkpoint_limit(&self) -> Option<usize> {
    +        self.chain_graph.checkpoint_limit()
    +    }
    +
    +    /// Set the checkpoint limit of the internal [`SparseChain`].
    +    ///
    +    /// Refer to [`SparseChain::set_checkpoint_limit`] for more.
    +    pub fn set_checkpoint_limit(&mut self, limit: Option<usize>) {
    +        self.chain_graph.set_checkpoint_limit(limit)
    +    }
    +
    +    /// Determines the resultant [`KeychainChangeSet`] if the given [`KeychainScan`] is applied.
    +    ///
    +    /// Internally, we call [`ChainGraph::determine_changeset`] and also determine the additions of
    +    /// [`KeychainTxOutIndex`].
    +    pub fn determine_changeset(
    +        &self,
    +        scan: &KeychainScan<K, P>,
    +    ) -> Result<KeychainChangeSet<K, P>, chain_graph::UpdateError<P>> {
    +        // TODO: `KeychainTxOutIndex::determine_additions`
    +        let mut derivation_indices = scan.last_active_indices.clone();
    +        derivation_indices.retain(|keychain, index| {
    +            match self.txout_index.last_revealed_index(keychain) {
    +                Some(existing) => *index > existing,
    +                None => true,
    +            }
    +        });
    +
    +        Ok(KeychainChangeSet {
    +            derivation_indices: DerivationAdditions(derivation_indices),
    +            chain_graph: self.chain_graph.determine_changeset(&scan.update)?,
    +        })
    +    }
    +
    +    /// Directly applies a [`KeychainScan`] on [`KeychainTracker`].
    +    ///
    +    /// This is equivilant to calling [`determine_changeset`] and [`apply_changeset`] in sequence.
    +    ///
    +    /// [`determine_changeset`]: Self::determine_changeset
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    pub fn apply_update(
    +        &mut self,
    +        scan: KeychainScan<K, P>,
    +    ) -> Result<KeychainChangeSet<K, P>, chain_graph::UpdateError<P>> {
    +        let changeset = self.determine_changeset(&scan)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Applies the changes in `changeset` to [`KeychainTracker`].
    +    ///
    +    /// Internally, this calls [`KeychainTxOutIndex::apply_additions`] and
    +    /// [`ChainGraph::apply_changeset`] in sequence.
    +    pub fn apply_changeset(&mut self, changeset: KeychainChangeSet<K, P>) {
    +        let KeychainChangeSet {
    +            derivation_indices,
    +            chain_graph,
    +        } = changeset;
    +        self.txout_index.apply_additions(derivation_indices);
    +        let _ = self.txout_index.scan(&chain_graph);
    +        self.chain_graph.apply_changeset(chain_graph)
    +    }
    +
    +    /// Iterates through [`FullTxOut`]s that are considered to exist in our representation of the
    +    /// blockchain/mempool.
    +    ///
    +    /// In other words, these are `txout`s of confirmed and in-mempool transactions, based on our
    +    /// view of the blockchain/mempool.
    +    pub fn full_txouts(&self) -> impl Iterator<Item = (&(K, u32), FullTxOut<P>)> + '_ {
    +        self.txout_index
    +            .txouts()
    +            .filter_map(move |(spk_i, op, _)| Some((spk_i, self.chain_graph.full_txout(op)?)))
    +    }
    +
    +    /// Iterates through [`FullTxOut`]s that are unspent outputs.
    +    ///
    +    /// Refer to [`full_txouts`] for more.
    +    ///
    +    /// [`full_txouts`]: Self::full_txouts
    +    pub fn full_utxos(&self) -> impl Iterator<Item = (&(K, u32), FullTxOut<P>)> + '_ {
    +        self.full_txouts()
    +            .filter(|(_, txout)| txout.spent_by.is_none())
    +    }
    +
    +    /// Returns a reference to the internal [`ChainGraph`].
    +    pub fn chain_graph(&self) -> &ChainGraph<P> {
    +        &self.chain_graph
    +    }
    +
    +    /// Returns a reference to the internal [`TxGraph`] (which is part of the [`ChainGraph`]).
    +    pub fn graph(&self) -> &TxGraph {
    +        self.chain_graph().graph()
    +    }
    +
    +    /// Returns a reference to the internal [`SparseChain`] (which is part of the [`ChainGraph`]).
    +    pub fn chain(&self) -> &SparseChain<P> {
    +        self.chain_graph().chain()
    +    }
    +
    +    /// Determines the changes as result of inserting `block_id` (a height and block hash) into the
    +    /// tracker.
    +    ///
    +    /// The caller is responsible for guaranteeing that a block exists at that height. If a
    +    /// checkpoint already exists at that height with a different hash this will return an error.
    +    /// Otherwise it will return `Ok(true)` if the checkpoint didn't already exist or `Ok(false)`
    +    /// if it did.
    +    ///
    +    /// **Warning**: This function modifies the internal state of the tracker. You are responsible
    +    /// for persisting these changes to disk if you need to restore them.
    +    pub fn insert_checkpoint_preview(
    +        &self,
    +        block_id: BlockId,
    +    ) -> Result<KeychainChangeSet<K, P>, chain_graph::InsertCheckpointError> {
    +        Ok(KeychainChangeSet {
    +            chain_graph: self.chain_graph.insert_checkpoint_preview(block_id)?,
    +            ..Default::default()
    +        })
    +    }
    +
    +    /// Directly insert a `block_id` into the tracker.
    +    ///
    +    /// This is equivalent of calling [`insert_checkpoint_preview`] and [`apply_changeset`] in
    +    /// sequence.
    +    ///
    +    /// [`insert_checkpoint_preview`]: Self::insert_checkpoint_preview
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    pub fn insert_checkpoint(
    +        &mut self,
    +        block_id: BlockId,
    +    ) -> Result<KeychainChangeSet<K, P>, chain_graph::InsertCheckpointError> {
    +        let changeset = self.insert_checkpoint_preview(block_id)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Determines the changes as result of inserting a transaction into the inner [`ChainGraph`]
    +    /// and optionally into the inner chain at `position`.
    +    ///
    +    /// **Warning**: This function modifies the internal state of the chain graph. You are
    +    /// responsible for persisting these changes to disk if you need to restore them.
    +    pub fn insert_tx_preview(
    +        &self,
    +        tx: Transaction,
    +        pos: P,
    +    ) -> Result<KeychainChangeSet<K, P>, chain_graph::InsertTxError<P>> {
    +        Ok(KeychainChangeSet {
    +            chain_graph: self.chain_graph.insert_tx_preview(tx, pos)?,
    +            ..Default::default()
    +        })
    +    }
    +
    +    /// Directly insert a transaction into the inner [`ChainGraph`] and optionally into the inner
    +    /// chain at `position`.
    +    ///
    +    /// This is equivilant of calling [`insert_tx_preview`] and [`apply_changeset`] in sequence.
    +    ///
    +    /// [`insert_tx_preview`]: Self::insert_tx_preview
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    pub fn insert_tx(
    +        &mut self,
    +        tx: Transaction,
    +        pos: P,
    +    ) -> Result<KeychainChangeSet<K, P>, chain_graph::InsertTxError<P>> {
    +        let changeset = self.insert_tx_preview(tx, pos)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Returns the *balance* of the keychain i.e. the value of unspent transaction outputs tracked.
    +    ///
    +    /// The caller provides a `should_trust` predicate which must decide whether the value of
    +    /// unconfirmed outputs on this keychain are guaranteed to be realized or not. For example:
    +    ///
    +    /// - For an *internal* (change) keychain `should_trust` should in general be `true` since even if
    +    /// you lose an internal output due to eviction you will always gain back the value from whatever output the
    +    /// unconfirmed transaction was spending (since that output is presumeably from your wallet).
    +    /// - For an *external* keychain you might want `should_trust` to return  `false` since someone may cancel (by double spending)
    +    /// a payment made to addresses on that keychain.
    +    ///
    +    /// When in doubt set `should_trust` to return false. This doesn't do anything other than change
    +    /// where the unconfirmed output's value is accounted for in `Balance`.
    +    pub fn balance(&self, mut should_trust: impl FnMut(&K) -> bool) -> Balance {
    +        let mut immature = 0;
    +        let mut trusted_pending = 0;
    +        let mut untrusted_pending = 0;
    +        let mut confirmed = 0;
    +        let last_sync_height = self.chain().latest_checkpoint().map(|latest| latest.height);
    +        for ((keychain, _), utxo) in self.full_utxos() {
    +            let chain_position = &utxo.chain_position;
    +
    +            match chain_position.height() {
    +                TxHeight::Confirmed(_) => {
    +                    if utxo.is_on_coinbase {
    +                        if utxo.is_mature(
    +                            last_sync_height
    +                                .expect("since it's confirmed we must have a checkpoint"),
    +                        ) {
    +                            confirmed += utxo.txout.value;
    +                        } else {
    +                            immature += utxo.txout.value;
    +                        }
    +                    } else {
    +                        confirmed += utxo.txout.value;
    +                    }
    +                }
    +                TxHeight::Unconfirmed => {
    +                    if should_trust(keychain) {
    +                        trusted_pending += utxo.txout.value;
    +                    } else {
    +                        untrusted_pending += utxo.txout.value;
    +                    }
    +                }
    +            }
    +        }
    +
    +        Balance {
    +            immature,
    +            trusted_pending,
    +            untrusted_pending,
    +            confirmed,
    +        }
    +    }
    +
    +    /// Returns the balance of all spendable confirmed unspent outputs of this tracker at a
    +    /// particular height.
    +    pub fn balance_at(&self, height: u32) -> u64 {
    +        self.full_txouts()
    +            .filter(|(_, full_txout)| full_txout.is_spendable_at(height))
    +            .map(|(_, full_txout)| full_txout.txout.value)
    +            .sum()
    +    }
    +}
    +
    +impl<K, P> Default for KeychainTracker<K, P> {
    +    fn default() -> Self {
    +        Self {
    +            txout_index: Default::default(),
    +            chain_graph: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<K, P> AsRef<SparseChain<P>> for KeychainTracker<K, P> {
    +    fn as_ref(&self) -> &SparseChain<P> {
    +        self.chain_graph.chain()
    +    }
    +}
    +
    +impl<K, P> AsRef<TxGraph> for KeychainTracker<K, P> {
    +    fn as_ref(&self) -> &TxGraph {
    +        self.chain_graph.graph()
    +    }
    +}
    +
    +impl<K, P> AsRef<ChainGraph<P>> for KeychainTracker<K, P> {
    +    fn as_ref(&self) -> &ChainGraph<P> {
    +        &self.chain_graph
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/txout_index.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/txout_index.rs.html new file mode 100644 index 0000000000..5501685586 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/keychain/txout_index.rs.html @@ -0,0 +1,1184 @@ +txout_index.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +589
    +590
    +591
    +
    use crate::{
    +    collections::*,
    +    miniscript::{Descriptor, DescriptorPublicKey},
    +    ForEachTxOut, SpkTxOutIndex,
    +};
    +use alloc::{borrow::Cow, vec::Vec};
    +use bitcoin::{secp256k1::Secp256k1, OutPoint, Script, TxOut};
    +use core::{fmt::Debug, ops::Deref};
    +
    +use super::DerivationAdditions;
    +
    +/// Maximum [BIP32](https://bips.xyz/32) derivation index.
    +pub const BIP32_MAX_INDEX: u32 = (1 << 31) - 1;
    +
    +/// A convenient wrapper around [`SpkTxOutIndex`] that relates script pubkeys to miniscript public
    +/// [`Descriptor`]s.
    +///
    +/// Descriptors are referenced by the provided keychain generic (`K`).
    +///
    +/// Script pubkeys for a descriptor are revealed chronologically from index 0. I.e. If the last
    +/// revealed index of a descriptor is 5, scripts of indices 0 to 4 are guaranteed to already be
    +/// revealed. In addition to revealed scripts, we have a `lookahead` parameter for each keychain
    +/// which defines the number of script pubkeys to store ahead of the last revealed index.
    +///
    +/// Methods that could update the last revealed index will return [`DerivationAdditions`] to report
    +/// these changes. This can be persisted for future recovery.
    +///
    +/// ## Synopsis
    +///
    +/// ```
    +/// use bdk_chain::keychain::KeychainTxOutIndex;
    +/// # use bdk_chain::{ miniscript::{Descriptor, DescriptorPublicKey} };
    +/// # use core::str::FromStr;
    +///
    +/// // imagine our service has internal and external addresses but also addresses for users
    +/// #[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
    +/// enum MyKeychain {
    +///     External,
    +///     Internal,
    +///     MyAppUser {
    +///         user_id: u32
    +///     }
    +/// }
    +///
    +/// let mut txout_index = KeychainTxOutIndex::<MyKeychain>::default();
    +///
    +/// # let secp = bdk_chain::bitcoin::secp256k1::Secp256k1::signing_only();
    +/// # let (external_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/0/*)").unwrap();
    +/// # let (internal_descriptor,_) = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, "tr([73c5da0a/86'/0'/0']xprv9xgqHN7yz9MwCkxsBPN5qetuNdQSUttZNKw1dcYTV4mkaAFiBVGQziHs3NRSWMkCzvgjEe3n9xV8oYywvM8at9yRqyaZVz6TYYhX98VjsUk/1/*)").unwrap();
    +/// # let descriptor_for_user_42 = external_descriptor.clone();
    +/// txout_index.add_keychain(MyKeychain::External, external_descriptor);
    +/// txout_index.add_keychain(MyKeychain::Internal, internal_descriptor);
    +/// txout_index.add_keychain(MyKeychain::MyAppUser { user_id: 42 }, descriptor_for_user_42);
    +///
    +/// let new_spk_for_user = txout_index.reveal_next_spk(&MyKeychain::MyAppUser{ user_id: 42 });
    +/// ```
    +///
    +/// [`Ord`]: core::cmp::Ord
    +/// [`SpkTxOutIndex`]: crate::spk_txout_index::SpkTxOutIndex
    +/// [`Descriptor`]: crate::miniscript::Descriptor
    +#[derive(Clone, Debug)]
    +pub struct KeychainTxOutIndex<K> {
    +    inner: SpkTxOutIndex<(K, u32)>,
    +    // descriptors of each keychain
    +    keychains: BTreeMap<K, Descriptor<DescriptorPublicKey>>,
    +    // last stored indexes
    +    last_revealed: BTreeMap<K, u32>,
    +    // lookahead settings for each keychain
    +    lookahead: BTreeMap<K, u32>,
    +}
    +
    +impl<K> Default for KeychainTxOutIndex<K> {
    +    fn default() -> Self {
    +        Self {
    +            inner: SpkTxOutIndex::default(),
    +            keychains: BTreeMap::default(),
    +            last_revealed: BTreeMap::default(),
    +            lookahead: BTreeMap::default(),
    +        }
    +    }
    +}
    +
    +impl<K> Deref for KeychainTxOutIndex<K> {
    +    type Target = SpkTxOutIndex<(K, u32)>;
    +
    +    fn deref(&self) -> &Self::Target {
    +        &self.inner
    +    }
    +}
    +
    +impl<K: Clone + Ord + Debug> KeychainTxOutIndex<K> {
    +    /// Scans an object for relevant outpoints, which are stored and indexed internally.
    +    ///
    +    /// If the matched script pubkey is part of the lookahead, the last stored index is updated for
    +    /// the script pubkey's keychain and the [`DerivationAdditions`] returned will reflect the
    +    /// change.
    +    ///
    +    /// Typically this method is used in two situations:
    +    ///
    +    /// 1. After loading transaction data from disk you may scan over all the txouts to restore all
    +    /// your txouts.
    +    /// 2. When getting new data from the chain you usually scan it before incorporating it into
    +    /// your chain state (i.e. `SparseChain`, `ChainGraph`).
    +    ///
    +    /// See [`ForEachTxout`] for the types that support this.
    +    ///
    +    /// [`ForEachTxout`]: crate::ForEachTxOut
    +    pub fn scan(&mut self, txouts: &impl ForEachTxOut) -> DerivationAdditions<K> {
    +        let mut additions = DerivationAdditions::<K>::default();
    +        txouts.for_each_txout(|(op, txout)| additions.append(self.scan_txout(op, txout)));
    +        additions
    +    }
    +
    +    /// Scan a single outpoint for a matching script pubkey.
    +    ///
    +    /// If it matches the index will store and index it.
    +    pub fn scan_txout(&mut self, op: OutPoint, txout: &TxOut) -> DerivationAdditions<K> {
    +        match self.inner.scan_txout(op, txout).cloned() {
    +            Some((keychain, index)) => self.reveal_to_target(&keychain, index).1,
    +            None => DerivationAdditions::default(),
    +        }
    +    }
    +
    +    /// Return a reference to the internal [`SpkTxOutIndex`].
    +    pub fn inner(&self) -> &SpkTxOutIndex<(K, u32)> {
    +        &self.inner
    +    }
    +
    +    /// Return a reference to the internal map of keychain to descriptors.
    +    pub fn keychains(&self) -> &BTreeMap<K, Descriptor<DescriptorPublicKey>> {
    +        &self.keychains
    +    }
    +
    +    /// Add a keychain to the tracker's `txout_index` with a descriptor to derive addresses for it.
    +    ///
    +    /// Adding a keychain means you will be able to derive new script pubkeys under that keychain
    +    /// and the txout index will discover transaction outputs with those script pubkeys.
    +    ///
    +    /// # Panics
    +    ///
    +    /// This will panic if a different `descriptor` is introduced to the same `keychain`.
    +    pub fn add_keychain(&mut self, keychain: K, descriptor: Descriptor<DescriptorPublicKey>) {
    +        let old_descriptor = &*self.keychains.entry(keychain).or_insert(descriptor.clone());
    +        assert_eq!(
    +            &descriptor, old_descriptor,
    +            "keychain already contains a different descriptor"
    +        );
    +    }
    +
    +    /// Return the lookahead setting for each keychain.
    +    ///
    +    /// Refer to [`set_lookahead`] for a deeper explanation on `lookahead`.
    +    ///
    +    /// [`set_lookahead`]: Self::set_lookahead
    +    pub fn lookaheads(&self) -> &BTreeMap<K, u32> {
    +        &self.lookahead
    +    }
    +
    +    /// Convenience method to call [`set_lookahead`] for all keychains.
    +    ///
    +    /// [`set_lookahead`]: Self::set_lookahead
    +    pub fn set_lookahead_for_all(&mut self, lookahead: u32) {
    +        for keychain in &self.keychains.keys().cloned().collect::<Vec<_>>() {
    +            self.lookahead.insert(keychain.clone(), lookahead);
    +            self.replenish_lookahead(keychain);
    +        }
    +    }
    +
    +    /// Set the lookahead count for `keychain`.
    +    ///
    +    /// The lookahead is the number of scripts to cache ahead of the last stored script index. This
    +    /// is useful during a scan via [`scan`] or [`scan_txout`].
    +    ///
    +    /// # Panics
    +    ///
    +    /// This will panic if `keychain` does not exist.
    +    ///
    +    /// [`scan`]: Self::scan
    +    /// [`scan_txout`]: Self::scan_txout
    +    pub fn set_lookahead(&mut self, keychain: &K, lookahead: u32) {
    +        self.lookahead.insert(keychain.clone(), lookahead);
    +        self.replenish_lookahead(keychain);
    +    }
    +
    +    /// Convenience method to call [`lookahead_to_target`] for multiple keychains.
    +    ///
    +    /// [`lookahead_to_target`]: Self::lookahead_to_target
    +    pub fn lookahead_to_target_multi(&mut self, target_indexes: BTreeMap<K, u32>) {
    +        for (keychain, target_index) in target_indexes {
    +            self.lookahead_to_target(&keychain, target_index)
    +        }
    +    }
    +
    +    /// Store lookahead scripts until `target_index`.
    +    ///
    +    /// This does not change the `lookahead` setting.
    +    pub fn lookahead_to_target(&mut self, keychain: &K, target_index: u32) {
    +        let next_index = self.next_store_index(keychain);
    +        if let Some(temp_lookahead) = target_index.checked_sub(next_index).filter(|&v| v > 0) {
    +            let old_lookahead = self.lookahead.insert(keychain.clone(), temp_lookahead);
    +            self.replenish_lookahead(keychain);
    +
    +            // revert
    +            match old_lookahead {
    +                Some(lookahead) => self.lookahead.insert(keychain.clone(), lookahead),
    +                None => self.lookahead.remove(keychain),
    +            };
    +        }
    +    }
    +
    +    fn replenish_lookahead(&mut self, keychain: &K) {
    +        let descriptor = self.keychains.get(keychain).expect("keychain must exist");
    +        let next_store_index = self.next_store_index(keychain);
    +        let next_reveal_index = self.last_revealed.get(keychain).map_or(0, |v| *v + 1);
    +        let lookahead = self.lookahead.get(keychain).map_or(0, |v| *v);
    +
    +        for (new_index, new_spk) in range_descriptor_spks(
    +            Cow::Borrowed(descriptor),
    +            next_store_index..next_reveal_index + lookahead,
    +        ) {
    +            let _inserted = self
    +                .inner
    +                .insert_spk((keychain.clone(), new_index), new_spk);
    +            debug_assert!(_inserted, "replenish lookahead: must not have existing spk: keychain={:?}, lookahead={}, next_store_index={}, next_reveal_index={}", keychain, lookahead, next_store_index, next_reveal_index);
    +        }
    +    }
    +
    +    fn next_store_index(&self, keychain: &K) -> u32 {
    +        self.inner()
    +            .all_spks()
    +            .range((keychain.clone(), u32::MIN)..(keychain.clone(), u32::MAX))
    +            .last()
    +            .map_or(0, |((_, v), _)| *v + 1)
    +    }
    +
    +    /// Generates script pubkey iterators for every `keychain`. The iterators iterate over all
    +    /// derivable script pubkeys.
    +    pub fn spks_of_all_keychains(
    +        &self,
    +    ) -> BTreeMap<K, impl Iterator<Item = (u32, Script)> + Clone> {
    +        self.keychains
    +            .iter()
    +            .map(|(keychain, descriptor)| {
    +                (
    +                    keychain.clone(),
    +                    range_descriptor_spks(Cow::Owned(descriptor.clone()), 0..),
    +                )
    +            })
    +            .collect()
    +    }
    +
    +    /// Generates a script pubkey iterator for the given `keychain`'s descriptor (if exists). The
    +    /// iterator iterates over all derivable scripts of the keychain's descriptor.
    +    ///
    +    /// # Panics
    +    ///
    +    /// This will panic if `keychain` does not exist.
    +    pub fn spks_of_keychain(&self, keychain: &K) -> impl Iterator<Item = (u32, Script)> + Clone {
    +        let descriptor = self
    +            .keychains
    +            .get(keychain)
    +            .expect("keychain must exist")
    +            .clone();
    +        range_descriptor_spks(Cow::Owned(descriptor), 0..)
    +    }
    +
    +    /// Convenience method to get [`revealed_spks_of_keychain`] of all keychains.
    +    ///
    +    /// [`revealed_spks_of_keychain`]: Self::revealed_spks_of_keychain
    +    pub fn revealed_spks_of_all_keychains(
    +        &self,
    +    ) -> BTreeMap<K, impl Iterator<Item = (u32, &Script)> + Clone> {
    +        self.keychains
    +            .keys()
    +            .map(|keychain| (keychain.clone(), self.revealed_spks_of_keychain(keychain)))
    +            .collect()
    +    }
    +
    +    /// Iterates over the script pubkeys revealed by this index under `keychain`.
    +    pub fn revealed_spks_of_keychain(
    +        &self,
    +        keychain: &K,
    +    ) -> impl DoubleEndedIterator<Item = (u32, &Script)> + Clone {
    +        let next_index = self.last_revealed.get(keychain).map_or(0, |v| *v + 1);
    +        self.inner
    +            .all_spks()
    +            .range((keychain.clone(), u32::MIN)..(keychain.clone(), next_index))
    +            .map(|((_, derivation_index), spk)| (*derivation_index, spk))
    +    }
    +
    +    /// Get the next derivation index for `keychain`. This is the index after the last revealed
    +    /// derivation index.
    +    ///
    +    /// The second field in the returned tuple represents whether the next derivation index is new.
    +    /// There are two scenarios where the next derivation index is reused (not new):
    +    ///
    +    /// 1. The keychain's descriptor has no wildcard, and a script has already been revealed.
    +    /// 2. The number of revealed scripts has already reached 2^31 (refer to BIP-32).
    +    ///
    +    /// Not checking the second field of the tuple may result in address reuse.
    +    ///
    +    /// # Panics
    +    ///
    +    /// Panics if the `keychain` does not exist.
    +    pub fn next_index(&self, keychain: &K) -> (u32, bool) {
    +        let descriptor = self.keychains.get(keychain).expect("keychain must exist");
    +        let last_index = self.last_revealed.get(keychain).cloned();
    +
    +        // we can only get the next index if wildcard exists
    +        let has_wildcard = descriptor.has_wildcard();
    +
    +        match last_index {
    +            // if there is no index, next_index is always 0
    +            None => (0, true),
    +            // descriptors without wildcards can only have one index
    +            Some(_) if !has_wildcard => (0, false),
    +            // derivation index must be < 2^31 (BIP-32)
    +            Some(index) if index > BIP32_MAX_INDEX => {
    +                unreachable!("index is out of bounds")
    +            }
    +            Some(index) if index == BIP32_MAX_INDEX => (index, false),
    +            // get next derivation index
    +            Some(index) => (index + 1, true),
    +        }
    +    }
    +
    +    /// Get the last derivation index that is revealed for each keychain.
    +    ///
    +    /// Keychains with no revealed indices will not be included in the returned [`BTreeMap`].
    +    pub fn last_revealed_indices(&self) -> &BTreeMap<K, u32> {
    +        &self.last_revealed
    +    }
    +
    +    /// Get the last derivation index revealed for `keychain`.
    +    pub fn last_revealed_index(&self, keychain: &K) -> Option<u32> {
    +        self.last_revealed.get(keychain).cloned()
    +    }
    +
    +    /// Convenience method to call [`Self::reveal_to_target`] on multiple keychains.
    +    pub fn reveal_to_target_multi(
    +        &mut self,
    +        keychains: &BTreeMap<K, u32>,
    +    ) -> (
    +        BTreeMap<K, impl Iterator<Item = (u32, Script)>>,
    +        DerivationAdditions<K>,
    +    ) {
    +        let mut additions = DerivationAdditions::default();
    +        let mut spks = BTreeMap::new();
    +
    +        for (keychain, &index) in keychains {
    +            let (new_spks, new_additions) = self.reveal_to_target(keychain, index);
    +            if !new_additions.is_empty() {
    +                spks.insert(keychain.clone(), new_spks);
    +                additions.append(new_additions);
    +            }
    +        }
    +
    +        (spks, additions)
    +    }
    +
    +    /// Reveals script pubkeys of the `keychain`'s descriptor **up to and including** the
    +    /// `target_index`.
    +    ///
    +    /// If the `target_index` cannot be reached (due to the descriptor having no wildcard, and/or
    +    /// the `target_index` is in the hardened index range), this method will do a best-effort and
    +    /// reveal up to the last possible index.
    +    ///
    +    /// This returns an iterator of newly revealed indices (along side their scripts), and a
    +    /// [`DerivationAdditions`] which reports updates to the latest revealed index. If no new script
    +    /// pubkeys are revealed, both of these will be empty.
    +    ///
    +    /// # Panics
    +    ///
    +    /// Panics if `keychain` does not exist.
    +    pub fn reveal_to_target(
    +        &mut self,
    +        keychain: &K,
    +        target_index: u32,
    +    ) -> (impl Iterator<Item = (u32, Script)>, DerivationAdditions<K>) {
    +        let descriptor = self.keychains.get(keychain).expect("keychain must exist");
    +        let has_wildcard = descriptor.has_wildcard();
    +
    +        let target_index = if has_wildcard { target_index } else { 0 };
    +        let next_store_index = self.next_store_index(keychain);
    +        let next_reveal_index = self.last_revealed.get(keychain).map_or(0, |v| *v + 1);
    +        let lookahead = self.lookahead.get(keychain).map_or(0, |v| *v);
    +
    +        // if we are able to reveal new indexes, the latest revealed index goes here
    +        let mut revealed_index = None;
    +
    +        // if target is already surpassed, we have nothing to reveal
    +        if next_reveal_index <= target_index
    +            // if target is already stored (due to lookahead), this can be our new revealed index
    +            && target_index < next_reveal_index + lookahead
    +        {
    +            revealed_index = Some(target_index);
    +        }
    +
    +        // we range over indexes that are not stored
    +        let range = next_reveal_index + lookahead..=target_index + lookahead;
    +
    +        for (new_index, new_spk) in range_descriptor_spks(Cow::Borrowed(descriptor), range) {
    +            // no need to store if already stored
    +            if new_index >= next_store_index {
    +                let _inserted = self
    +                    .inner
    +                    .insert_spk((keychain.clone(), new_index), new_spk);
    +                debug_assert!(_inserted, "must not have existing spk",);
    +            }
    +
    +            // everything after `target_index` is stored for lookahead only
    +            if new_index <= target_index {
    +                revealed_index = Some(new_index);
    +            }
    +        }
    +
    +        match revealed_index {
    +            Some(index) => {
    +                let _old_index = self.last_revealed.insert(keychain.clone(), index);
    +                debug_assert!(_old_index < Some(index));
    +                (
    +                    range_descriptor_spks(
    +                        Cow::Owned(descriptor.clone()),
    +                        next_reveal_index..index + 1,
    +                    ),
    +                    DerivationAdditions(core::iter::once((keychain.clone(), index)).collect()),
    +                )
    +            }
    +            None => (
    +                range_descriptor_spks(
    +                    Cow::Owned(descriptor.clone()),
    +                    next_reveal_index..next_reveal_index,
    +                ),
    +                DerivationAdditions::default(),
    +            ),
    +        }
    +    }
    +
    +    /// Attempts to reveal the next script pubkey for `keychain`.
    +    ///
    +    /// Returns the derivation index of the revealed script pubkey, the revealed script pubkey and a
    +    /// [`DerivationAdditions`] which represents changes in the last revealed index (if any).
    +    ///
    +    /// When a new script cannot be revealed, we return the last revealed script and an empty
    +    /// [`DerivationAdditions`]. There are two scenarios when a new script pubkey cannot be derived:
    +    ///
    +    ///  1. The descriptor has no wildcard and already has one script revealed.
    +    ///  2. The descriptor has already revealed scripts up to the numeric bound.
    +    ///
    +    /// # Panics
    +    ///
    +    /// Panics if the `keychain` does not exist.
    +    pub fn reveal_next_spk(&mut self, keychain: &K) -> ((u32, &Script), DerivationAdditions<K>) {
    +        let (next_index, _) = self.next_index(keychain);
    +        let additions = self.reveal_to_target(keychain, next_index).1;
    +        let script = self
    +            .inner
    +            .spk_at_index(&(keychain.clone(), next_index))
    +            .expect("script must already be stored");
    +        ((next_index, script), additions)
    +    }
    +
    +    /// Gets the next unused script pubkey in the keychain. I.e. the script pubkey with the lowest
    +    /// index that has not been used yet.
    +    ///
    +    /// This will derive and reveal a new script pubkey if no more unused script pubkeys exist.
    +    ///
    +    /// If the descriptor has no wildcard and already has a used script pubkey, or if a descriptor
    +    /// has used all scripts up to the derivation bounds, the last derived script pubkey will be
    +    /// returned.
    +    ///
    +    /// # Panics
    +    ///
    +    /// Panics if `keychain` has never been added to the index
    +    pub fn next_unused_spk(&mut self, keychain: &K) -> ((u32, &Script), DerivationAdditions<K>) {
    +        let need_new = self.unused_spks_of_keychain(keychain).next().is_none();
    +        // this rather strange branch is needed because of some lifetime issues
    +        if need_new {
    +            self.reveal_next_spk(keychain)
    +        } else {
    +            (
    +                self.unused_spks_of_keychain(keychain)
    +                    .next()
    +                    .expect("we already know next exists"),
    +                DerivationAdditions::default(),
    +            )
    +        }
    +    }
    +
    +    /// Marks the script pubkey at `index` as used even though it hasn't seen an output with it.
    +    /// This only has an effect when the `index` had been added to `self` already and was unused.
    +    ///
    +    /// Returns whether the `index` was originally present as `unused`.
    +    ///
    +    /// This is useful when you want to reserve a script pubkey for something but don't want to add
    +    /// the transaction output using it to the index yet. Other callers will consider `index` on
    +    /// `keychain` used until you call [`unmark_used`].
    +    ///
    +    /// [`unmark_used`]: Self::unmark_used
    +    pub fn mark_used(&mut self, keychain: &K, index: u32) -> bool {
    +        self.inner.mark_used(&(keychain.clone(), index))
    +    }
    +
    +    /// Undoes the effect of [`mark_used`]. Returns whether the `index` is inserted back into
    +    /// `unused`.
    +    ///
    +    /// Note that if `self` has scanned an output with this script pubkey then this will have no
    +    /// effect.
    +    ///
    +    /// [`mark_used`]: Self::mark_used
    +    pub fn unmark_used(&mut self, keychain: &K, index: u32) -> bool {
    +        self.inner.unmark_used(&(keychain.clone(), index))
    +    }
    +
    +    /// Iterates over all unused script pubkeys for a `keychain` that have been stored in the index.
    +    pub fn unused_spks_of_keychain(
    +        &self,
    +        keychain: &K,
    +    ) -> impl DoubleEndedIterator<Item = (u32, &Script)> {
    +        let next_index = self.last_revealed.get(keychain).map_or(0, |&v| v + 1);
    +        let range = (keychain.clone(), u32::MIN)..(keychain.clone(), next_index);
    +        self.inner
    +            .unused_spks(range)
    +            .map(|((_, i), script)| (*i, script))
    +    }
    +
    +    /// Iterates over all the [`OutPoint`] that have a `TxOut` with a script pubkey derived from
    +    /// `keychain`.
    +    pub fn txouts_of_keychain(
    +        &self,
    +        keychain: &K,
    +    ) -> impl DoubleEndedIterator<Item = (u32, OutPoint)> + '_ {
    +        self.inner
    +            .outputs_in_range((keychain.clone(), u32::MIN)..(keychain.clone(), u32::MAX))
    +            .map(|((_, i), op)| (*i, op))
    +    }
    +
    +    /// Returns the highest derivation index of the `keychain` where [`KeychainTxOutIndex`] has
    +    /// found a [`TxOut`] with it's script pubkey.
    +    pub fn last_used_index(&self, keychain: &K) -> Option<u32> {
    +        self.txouts_of_keychain(keychain).last().map(|(i, _)| i)
    +    }
    +
    +    /// Returns the highest derivation index of each keychain that [`KeychainTxOutIndex`] has found
    +    /// a [`TxOut`] with it's script pubkey.
    +    pub fn last_used_indices(&self) -> BTreeMap<K, u32> {
    +        self.keychains
    +            .iter()
    +            .filter_map(|(keychain, _)| {
    +                self.last_used_index(keychain)
    +                    .map(|index| (keychain.clone(), index))
    +            })
    +            .collect()
    +    }
    +
    +    /// Applies the derivation additions to the [`KeychainTxOutIndex`], extending the number of
    +    /// derived scripts per keychain, as specified in the `additions`.
    +    pub fn apply_additions(&mut self, additions: DerivationAdditions<K>) {
    +        let _ = self.reveal_to_target_multi(&additions.0);
    +    }
    +}
    +
    +fn range_descriptor_spks<'a, R>(
    +    descriptor: Cow<'a, Descriptor<DescriptorPublicKey>>,
    +    range: R,
    +) -> impl Iterator<Item = (u32, Script)> + Clone + Send + 'a
    +where
    +    R: Iterator<Item = u32> + Clone + Send + 'a,
    +{
    +    let secp = Secp256k1::verification_only();
    +    let has_wildcard = descriptor.has_wildcard();
    +    range
    +        .into_iter()
    +        // non-wildcard descriptors can only have one derivation index (0)
    +        .take_while(move |&index| has_wildcard || index == 0)
    +        // we can only iterate over non-hardened indices
    +        .take_while(|&index| index <= BIP32_MAX_INDEX)
    +        .map(
    +            move |index| -> Result<_, miniscript::descriptor::ConversionError> {
    +                Ok((
    +                    index,
    +                    descriptor
    +                        .at_derivation_index(index)
    +                        .derived_descriptor(&secp)?
    +                        .script_pubkey(),
    +                ))
    +            },
    +        )
    +        .take_while(Result::is_ok)
    +        .map(Result::unwrap)
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/lib.rs.html new file mode 100644 index 0000000000..73c3b25bbb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/lib.rs.html @@ -0,0 +1,180 @@ +lib.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +
    //! This crate is a collection of core structures for [Bitcoin Dev Kit] (alpha release).
    +//!
    +//! The goal of this crate is give wallets the mechanisms needed to:
    +//!
    +//! 1. Figure out what data they need to fetch.
    +//! 2. Process that data in a way that never leads to inconsistent states.
    +//! 3. Fully index that data and expose it so that it can be consumed without friction.
    +//!
    +//! Our design goals for these mechanisms are:
    +//!
    +//! 1. Data source agnostic -- nothing in `bdk_chain` cares about where you get data from or whether
    +//!    you do it synchronously or asynchronously. If you know a fact about the blockchain you can just
    +//!    tell `bdk_chain`'s APIs about it and that information will be integrated if it can be done
    +//!    consistently.
    +//! 2. Error free APIs.
    +//! 3. Data persistence agnostic -- `bdk_chain` does not care where you cache on-chain data, what you
    +//!    cache or how you fetch it.
    +//!
    +//! [Bitcoin Dev Kit]: https://bitcoindevkit.org/
    +#![no_std]
    +pub use bitcoin;
    +pub mod chain_graph;
    +mod spk_txout_index;
    +pub use spk_txout_index::*;
    +mod chain_data;
    +pub use chain_data::*;
    +pub mod keychain;
    +pub mod sparse_chain;
    +mod tx_data_traits;
    +pub mod tx_graph;
    +pub use tx_data_traits::*;
    +
    +#[doc(hidden)]
    +pub mod example_utils;
    +
    +#[cfg(feature = "miniscript")]
    +pub use miniscript;
    +#[cfg(feature = "miniscript")]
    +mod descriptor_ext;
    +#[cfg(feature = "miniscript")]
    +pub use descriptor_ext::DescriptorExt;
    +
    +#[allow(unused_imports)]
    +#[macro_use]
    +extern crate alloc;
    +
    +#[cfg(feature = "serde")]
    +pub extern crate serde_crate as serde;
    +
    +#[cfg(feature = "bincode")]
    +extern crate bincode;
    +
    +#[cfg(feature = "std")]
    +#[macro_use]
    +extern crate std;
    +
    +#[cfg(all(not(feature = "std"), feature = "hashbrown"))]
    +extern crate hashbrown;
    +
    +// When no-std use `alloc`'s Hash collections. This is activated by default
    +#[cfg(all(not(feature = "std"), not(feature = "hashbrown")))]
    +#[doc(hidden)]
    +pub mod collections {
    +    #![allow(dead_code)]
    +    pub type HashSet<K> = alloc::collections::BTreeSet<K>;
    +    pub type HashMap<K, V> = alloc::collections::BTreeMap<K, V>;
    +    pub use alloc::collections::{btree_map as hash_map, *};
    +}
    +
    +// When we have std use `std`'s all collections
    +#[cfg(all(feature = "std", not(feature = "hashbrown")))]
    +#[doc(hidden)]
    +pub mod collections {
    +    pub use std::collections::{hash_map, *};
    +}
    +
    +// With special feature `hashbrown` use `hashbrown`'s hash collections, and else from `alloc`.
    +#[cfg(feature = "hashbrown")]
    +#[doc(hidden)]
    +pub mod collections {
    +    #![allow(dead_code)]
    +    pub type HashSet<K> = hashbrown::HashSet<K>;
    +    pub type HashMap<K, V> = hashbrown::HashMap<K, V>;
    +    pub use alloc::collections::*;
    +    pub use hashbrown::hash_map;
    +}
    +
    +/// How many confirmations are needed for a coinbase output to be spent
    +pub const COINBASE_MATURITY: u32 = 100;
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/sparse_chain.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/sparse_chain.rs.html new file mode 100644 index 0000000000..216ff1cebe --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/sparse_chain.rs.html @@ -0,0 +1,2206 @@ +sparse_chain.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +589
    +590
    +591
    +592
    +593
    +594
    +595
    +596
    +597
    +598
    +599
    +600
    +601
    +602
    +603
    +604
    +605
    +606
    +607
    +608
    +609
    +610
    +611
    +612
    +613
    +614
    +615
    +616
    +617
    +618
    +619
    +620
    +621
    +622
    +623
    +624
    +625
    +626
    +627
    +628
    +629
    +630
    +631
    +632
    +633
    +634
    +635
    +636
    +637
    +638
    +639
    +640
    +641
    +642
    +643
    +644
    +645
    +646
    +647
    +648
    +649
    +650
    +651
    +652
    +653
    +654
    +655
    +656
    +657
    +658
    +659
    +660
    +661
    +662
    +663
    +664
    +665
    +666
    +667
    +668
    +669
    +670
    +671
    +672
    +673
    +674
    +675
    +676
    +677
    +678
    +679
    +680
    +681
    +682
    +683
    +684
    +685
    +686
    +687
    +688
    +689
    +690
    +691
    +692
    +693
    +694
    +695
    +696
    +697
    +698
    +699
    +700
    +701
    +702
    +703
    +704
    +705
    +706
    +707
    +708
    +709
    +710
    +711
    +712
    +713
    +714
    +715
    +716
    +717
    +718
    +719
    +720
    +721
    +722
    +723
    +724
    +725
    +726
    +727
    +728
    +729
    +730
    +731
    +732
    +733
    +734
    +735
    +736
    +737
    +738
    +739
    +740
    +741
    +742
    +743
    +744
    +745
    +746
    +747
    +748
    +749
    +750
    +751
    +752
    +753
    +754
    +755
    +756
    +757
    +758
    +759
    +760
    +761
    +762
    +763
    +764
    +765
    +766
    +767
    +768
    +769
    +770
    +771
    +772
    +773
    +774
    +775
    +776
    +777
    +778
    +779
    +780
    +781
    +782
    +783
    +784
    +785
    +786
    +787
    +788
    +789
    +790
    +791
    +792
    +793
    +794
    +795
    +796
    +797
    +798
    +799
    +800
    +801
    +802
    +803
    +804
    +805
    +806
    +807
    +808
    +809
    +810
    +811
    +812
    +813
    +814
    +815
    +816
    +817
    +818
    +819
    +820
    +821
    +822
    +823
    +824
    +825
    +826
    +827
    +828
    +829
    +830
    +831
    +832
    +833
    +834
    +835
    +836
    +837
    +838
    +839
    +840
    +841
    +842
    +843
    +844
    +845
    +846
    +847
    +848
    +849
    +850
    +851
    +852
    +853
    +854
    +855
    +856
    +857
    +858
    +859
    +860
    +861
    +862
    +863
    +864
    +865
    +866
    +867
    +868
    +869
    +870
    +871
    +872
    +873
    +874
    +875
    +876
    +877
    +878
    +879
    +880
    +881
    +882
    +883
    +884
    +885
    +886
    +887
    +888
    +889
    +890
    +891
    +892
    +893
    +894
    +895
    +896
    +897
    +898
    +899
    +900
    +901
    +902
    +903
    +904
    +905
    +906
    +907
    +908
    +909
    +910
    +911
    +912
    +913
    +914
    +915
    +916
    +917
    +918
    +919
    +920
    +921
    +922
    +923
    +924
    +925
    +926
    +927
    +928
    +929
    +930
    +931
    +932
    +933
    +934
    +935
    +936
    +937
    +938
    +939
    +940
    +941
    +942
    +943
    +944
    +945
    +946
    +947
    +948
    +949
    +950
    +951
    +952
    +953
    +954
    +955
    +956
    +957
    +958
    +959
    +960
    +961
    +962
    +963
    +964
    +965
    +966
    +967
    +968
    +969
    +970
    +971
    +972
    +973
    +974
    +975
    +976
    +977
    +978
    +979
    +980
    +981
    +982
    +983
    +984
    +985
    +986
    +987
    +988
    +989
    +990
    +991
    +992
    +993
    +994
    +995
    +996
    +997
    +998
    +999
    +1000
    +1001
    +1002
    +1003
    +1004
    +1005
    +1006
    +1007
    +1008
    +1009
    +1010
    +1011
    +1012
    +1013
    +1014
    +1015
    +1016
    +1017
    +1018
    +1019
    +1020
    +1021
    +1022
    +1023
    +1024
    +1025
    +1026
    +1027
    +1028
    +1029
    +1030
    +1031
    +1032
    +1033
    +1034
    +1035
    +1036
    +1037
    +1038
    +1039
    +1040
    +1041
    +1042
    +1043
    +1044
    +1045
    +1046
    +1047
    +1048
    +1049
    +1050
    +1051
    +1052
    +1053
    +1054
    +1055
    +1056
    +1057
    +1058
    +1059
    +1060
    +1061
    +1062
    +1063
    +1064
    +1065
    +1066
    +1067
    +1068
    +1069
    +1070
    +1071
    +1072
    +1073
    +1074
    +1075
    +1076
    +1077
    +1078
    +1079
    +1080
    +1081
    +1082
    +1083
    +1084
    +1085
    +1086
    +1087
    +1088
    +1089
    +1090
    +1091
    +1092
    +1093
    +1094
    +1095
    +1096
    +1097
    +1098
    +1099
    +1100
    +1101
    +1102
    +
    //! Module for structures that maintain sparse (purposely incomplete) snapshots of blockchain data.
    +//!
    +//! [`SparseChain`] stores [`Txid`]s ordered by an index that implements [`ChainPosition`] (this
    +//! represents the transaction's position in the blockchain, by default [`TxHeight`] is used).
    +//! [`SparseChain`] also contains "checkpoints" which relate block height to block hash. Changes to
    +//! a [`SparseChain`] are reported by returning [`ChangeSet`]s.
    +//!
    +//! # Updating [`SparseChain`]
    +//!
    +//! A sparsechain can be thought of as a consistent snapshot of history. A [`SparseChain`] can be
    +//! updated by applying an update [`SparseChain`] on top, but only if they "connect" via their
    +//! checkpoints and don't result in unexpected movements of transactions.
    +//!
    +//! ```
    +//! # use bdk_chain::{BlockId, TxHeight, sparse_chain::*, example_utils::*};
    +//! # use bitcoin::BlockHash;
    +//! # let hash_a = new_hash::<BlockHash>("a");
    +//! # let hash_b = new_hash::<BlockHash>("b");
    +//! # let hash_c = new_hash::<BlockHash>("c");
    +//! # let hash_d = new_hash::<BlockHash>("d");
    +//! // create empty sparsechain
    +//! let mut chain = SparseChain::<TxHeight>::default();
    +//!
    +//! /* Updating an empty sparsechain will always succeed */
    +//!
    +//! let update = SparseChain::from_checkpoints(vec![
    +//!     BlockId {
    +//!         height: 1,
    +//!         hash: hash_a,
    +//!     },
    +//!     BlockId {
    +//!         height: 2,
    +//!         hash: hash_b,
    +//!     },
    +//! ]);
    +//! let _ = chain
    +//!     .apply_update(update)
    +//!     .expect("updating an empty sparsechain will always succeed");
    +//!
    +//! /* To update a non-empty sparsechain, the update must connect */
    +//!
    +//! let update = SparseChain::from_checkpoints(vec![
    +//!     BlockId {
    +//!         height: 2,
    +//!         hash: hash_b,
    +//!     },
    +//!     BlockId {
    +//!         height: 3,
    +//!         hash: hash_c,
    +//!     },
    +//! ]);
    +//! let _ = chain
    +//!     .apply_update(update)
    +//!     .expect("we have connected at block height 2, so this must succeed");
    +//! ```
    +//!
    +//! ## Invalid updates
    +//!
    +//! As shown above, sparsechains can be "connected" by comparing their checkpoints. However, there
    +//! are situations where two sparsechains cannot connect in a way that guarantees consistency.
    +//!
    +//! ```
    +//! # use bdk_chain::{BlockId, TxHeight, sparse_chain::*, example_utils::*};
    +//! # use bitcoin::BlockHash;
    +//! # let hash_a = new_hash::<BlockHash>("a");
    +//! # let hash_b = new_hash::<BlockHash>("b");
    +//! # let hash_c = new_hash::<BlockHash>("c");
    +//! # let hash_d = new_hash::<BlockHash>("d");
    +//! // our sparsechain has 2 checkpoints
    +//! let chain = SparseChain::<TxHeight>::from_checkpoints(vec![
    +//!     BlockId {
    +//!         height: 1,
    +//!         hash: hash_a,
    +//!     },
    +//!     BlockId {
    +//!         height: 2,
    +//!         hash: hash_b,
    +//!     },
    +//! ]);
    +//!
    +//! /* Example of an ambiguous update that does not fully connect */
    +//!
    +//! let ambiguous_update = SparseChain::from_checkpoints(vec![
    +//!     // the update sort of "connects" at checkpoint 1, but...
    +//!     BlockId {
    +//!         height: 1,
    +//!         hash: hash_a,
    +//!     },
    +//!     // we cannot determine whether checkpoint 3 connects with checkpoint 2
    +//!     BlockId {
    +//!         height: 3,
    +//!         hash: hash_c,
    +//!     },
    +//! ]);
    +//! let _ = chain
    +//!     .determine_changeset(&ambiguous_update)
    +//!     .expect_err("cannot apply ambiguous update");
    +//!
    +//! /* Example of an update that completely misses the point */
    +//!
    +//! let disconnected_update = SparseChain::from_checkpoints(vec![
    +//!     // the last checkpoint in chain is 2, so 3 and 4 do not connect
    +//!     BlockId {
    +//!         height: 3,
    +//!         hash: hash_c,
    +//!     },
    +//!     BlockId {
    +//!         height: 4,
    +//!         hash: hash_d,
    +//!     },
    +//! ]);
    +//! let _ = chain
    +//!     .determine_changeset(&disconnected_update)
    +//!     .expect_err("cannot apply a totally-disconnected update");
    +//! ```
    +//!
    +//! ## Handling reorgs
    +//!
    +//! Updates can be formed to evict data from the original sparsechain. This is useful for handling
    +//! blockchain reorgs.
    +//!
    +//! ```
    +//! # use bdk_chain::{BlockId, TxHeight, sparse_chain::*, example_utils::*};
    +//! # use bitcoin::BlockHash;
    +//! # let hash_a = new_hash::<BlockHash>("a");
    +//! # let hash_b = new_hash::<BlockHash>("b");
    +//! # let hash_c = new_hash::<BlockHash>("c");
    +//! # let hash_d = new_hash::<BlockHash>("d");
    +//! // our chain has a single checkpoint at height 11
    +//! let mut chain = SparseChain::<TxHeight>::from_checkpoints(vec![BlockId {
    +//!     height: 11,
    +//!     hash: hash_a,
    +//! }]);
    +//!
    +//! // we detect a reorg at height 11, and we introduce a new checkpoint at height 12
    +//! let update = SparseChain::from_checkpoints(vec![
    +//!     BlockId {
    +//!         height: 11,
    +//!         hash: hash_b,
    +//!     },
    +//!     BlockId {
    +//!         height: 12,
    +//!         hash: hash_c,
    +//!     },
    +//! ]);
    +//! let _ = chain
    +//!     .apply_update(update)
    +//!     .expect("we can evict/replace checkpoint 11 since it is the only checkpoint");
    +//!
    +//! // now our `chain` has 2 checkpoints (11:hash_b & 12:hash_c)
    +//! // we detect another reorg, this time at height 12...
    +//! let update = SparseChain::from_checkpoints(vec![
    +//!     // we connect at checkpoint 11 as this is our "point of agreement"
    +//!     BlockId {
    +//!         height: 11,
    +//!         hash: hash_b,
    +//!     },
    +//!     BlockId {
    +//!         height: 12,
    +//!         hash: hash_d,
    +//!     },
    +//! ]);
    +//! let _ = chain
    +//!     .apply_update(update)
    +//!     .expect("we have provided a valid point of agreement, so our reorg update will succeed");
    +//! ```
    +//!
    +//! ## Movement of transactions during update
    +//!
    +//! If the original sparsechain and update sparsechain contain the same transaction at different
    +//! [`ChainPosition`]s, the transaction is considered as "moved". There are various movements of a
    +//! transaction that are invalid and update will fail.
    +//!
    +//! Valid movements:
    +//!
    +//! * When the transaction moved from unconfirmed (in original) to confirmed (in update). In other
    +//!     words, confirming transactions are allowed!
    +//! * If there has been a reorg at height x, an originally confirmed transaction at height x or
    +//!     above, may move to another height (that is at x or above, including becoming unconfirmed).
    +//!
    +//! Invalid movements:
    +//!
    +//! * A confirmed transaction cannot move without a reorg.
    +//! * Even with a reorg, an originally confirmed transaction cannot be moved below the height of the
    +//!     reorg.
    +//!
    +//! # Custom [`ChainPosition`]
    +//!
    +//! [`SparseChain`] maintains a list of txids ordered by [`ChainPosition`]. By default, [`TxHeight`]
    +//! is used, however additional data can be incorporated into the implementation.
    +//!
    +//! For example, we can have "perfect ordering" of transactions if our positional index is a
    +//! combination of block height and transaction position in block.
    +//!
    +//! ```
    +//! # use bdk_chain::{BlockId, TxHeight, sparse_chain::*, example_utils::*};
    +//! # use bitcoin::{BlockHash, Txid};
    +//! # let hash_a = new_hash::<BlockHash>("a");
    +//! # let txid_1 = new_hash::<Txid>("1");
    +//! # let txid_2 = new_hash::<Txid>("2");
    +//! # let txid_3 = new_hash::<Txid>("3");
    +//! #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
    +//! pub enum TxPosition {
    +//!     Confirmed {
    +//!         height: u32,   // height of block
    +//!         position: u32, // position of transaction in the block
    +//!     },
    +//!     Unconfirmed,
    +//! }
    +//!
    +//! impl Default for TxPosition {
    +//!     fn default() -> Self {
    +//!         Self::Unconfirmed
    +//!     }
    +//! }
    +//!
    +//! impl ChainPosition for TxPosition {
    +//!     fn height(&self) -> TxHeight {
    +//!         match self {
    +//!             Self::Confirmed { height, .. } => TxHeight::Confirmed(*height),
    +//!             Self::Unconfirmed => TxHeight::Unconfirmed,
    +//!         }
    +//!     }
    +//!
    +//!     fn max_ord_of_height(height: TxHeight) -> Self {
    +//!         match height {
    +//!             TxHeight::Confirmed(height) => Self::Confirmed {
    +//!                 height,
    +//!                 position: u32::MAX,
    +//!             },
    +//!             TxHeight::Unconfirmed => Self::Unconfirmed,
    +//!         }
    +//!     }
    +//!
    +//!     fn min_ord_of_height(height: TxHeight) -> Self {
    +//!         match height {
    +//!             TxHeight::Confirmed(height) => Self::Confirmed {
    +//!                 height,
    +//!                 position: u32::MIN,
    +//!             },
    +//!             TxHeight::Unconfirmed => Self::Unconfirmed,
    +//!         }
    +//!     }
    +//! }
    +//!
    +//! let mut chain = SparseChain::<TxPosition>::default();
    +//! let _ = chain
    +//!     .insert_checkpoint(BlockId {
    +//!         height: 10,
    +//!         hash: hash_a,
    +//!     })
    +//!     .unwrap();
    +//! let _ = chain
    +//!     .insert_tx(
    +//!         txid_1,
    +//!         TxPosition::Confirmed {
    +//!             height: 9,
    +//!             position: 4321,
    +//!         },
    +//!     )
    +//!     .unwrap();
    +//! let _ = chain
    +//!     .insert_tx(
    +//!         txid_2,
    +//!         TxPosition::Confirmed {
    +//!             height: 9,
    +//!             position: 1234,
    +//!         },
    +//!     )
    +//!     .unwrap();
    +//! let _ = chain
    +//!     .insert_tx(
    +//!         txid_3,
    +//!         TxPosition::Confirmed {
    +//!             height: 10,
    +//!             position: 321,
    +//!         },
    +//!     )
    +//!     .unwrap();
    +//!
    +//! // transactions are ordered correctly
    +//! assert_eq!(
    +//!     chain.txids().collect::<Vec<_>>(),
    +//!     vec![
    +//!         &(
    +//!             TxPosition::Confirmed {
    +//!                 height: 9,
    +//!                 position: 1234
    +//!             },
    +//!             txid_2
    +//!         ),
    +//!         &(
    +//!             TxPosition::Confirmed {
    +//!                 height: 9,
    +//!                 position: 4321
    +//!             },
    +//!             txid_1
    +//!         ),
    +//!         &(
    +//!             TxPosition::Confirmed {
    +//!                 height: 10,
    +//!                 position: 321
    +//!             },
    +//!             txid_3
    +//!         ),
    +//!     ],
    +//! );
    +//! ```
    +use core::{
    +    fmt::Debug,
    +    ops::{Bound, RangeBounds},
    +};
    +
    +use crate::{collections::*, tx_graph::TxGraph, BlockId, FullTxOut, TxHeight};
    +use bitcoin::{hashes::Hash, BlockHash, OutPoint, Txid};
    +
    +/// This is a non-monotone structure that tracks relevant [`Txid`]s that are ordered by chain
    +/// position `P`.
    +///
    +/// We use [`BlockHash`]s alongside their chain height as "checkpoints" to enforce consistency.
    +///
    +/// To "merge" two [`SparseChain`]s, the [`ChangeSet`] can be calculated by calling
    +/// [`determine_changeset`] and applying the [`ChangeSet`] via [`apply_changeset`]. For convenience,
    +/// [`apply_update`] does the above two steps in one call.
    +///
    +/// Refer to [module-level documentation] for more.
    +///
    +/// [`determine_changeset`]: Self::determine_changeset
    +/// [`apply_changeset`]: Self::apply_changeset
    +/// [`apply_update`]: Self::apply_update
    +/// [module-level documentation]: crate::sparse_chain
    +#[derive(Clone, Debug, PartialEq)]
    +pub struct SparseChain<P = TxHeight> {
    +    /// Block height to checkpoint data.
    +    checkpoints: BTreeMap<u32, BlockHash>,
    +    /// Txids ordered by the pos `P`.
    +    ordered_txids: BTreeSet<(P, Txid)>,
    +    /// Confirmation heights of txids.
    +    txid_to_pos: HashMap<Txid, P>,
    +    /// Limit number of checkpoints.
    +    checkpoint_limit: Option<usize>,
    +}
    +
    +impl<P> AsRef<SparseChain<P>> for SparseChain<P> {
    +    fn as_ref(&self) -> &SparseChain<P> {
    +        self
    +    }
    +}
    +
    +impl<P> Default for SparseChain<P> {
    +    fn default() -> Self {
    +        Self {
    +            checkpoints: Default::default(),
    +            ordered_txids: Default::default(),
    +            txid_to_pos: Default::default(),
    +            checkpoint_limit: Default::default(),
    +        }
    +    }
    +}
    +
    +/// Represents a failure when trying to insert a [`Txid`] into [`SparseChain`].
    +#[derive(Clone, Debug, PartialEq)]
    +pub enum InsertTxError<P> {
    +    /// Occurs when the [`Txid`] is to be inserted at a hight higher than the [`SparseChain`]'s tip.
    +    TxTooHigh {
    +        txid: Txid,
    +        tx_height: u32,
    +        tip_height: Option<u32>,
    +    },
    +    /// Occurs when the [`Txid`] is already in the [`SparseChain`] and the insertion would result in
    +    /// an unexpected move in [`ChainPosition`].
    +    TxMovedUnexpectedly {
    +        txid: Txid,
    +        original_pos: P,
    +        update_pos: P,
    +    },
    +}
    +
    +impl<P: core::fmt::Debug> core::fmt::Display for InsertTxError<P> {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            InsertTxError::TxTooHigh {
    +                txid,
    +                tx_height,
    +                tip_height,
    +            } => write!(
    +                f,
    +                "txid ({}) cannot be inserted at height ({}) greater than chain tip ({:?})",
    +                txid, tx_height, tip_height
    +            ),
    +            InsertTxError::TxMovedUnexpectedly {
    +                txid,
    +                original_pos,
    +                update_pos,
    +            } => write!(
    +                f,
    +                "txid ({}) insertion resulted in an expected positional move from {:?} to {:?}",
    +                txid, original_pos, update_pos
    +            ),
    +        }
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl<P: core::fmt::Debug> std::error::Error for InsertTxError<P> {}
    +
    +/// Represents a failure when trying to insert a checkpoint into [`SparseChain`].
    +#[derive(Clone, Debug, PartialEq)]
    +pub enum InsertCheckpointError {
    +    /// Occurs when checkpoint of the same height already exists with a different [`BlockHash`].
    +    HashNotMatching {
    +        height: u32,
    +        original_hash: BlockHash,
    +        update_hash: BlockHash,
    +    },
    +}
    +
    +impl core::fmt::Display for InsertCheckpointError {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        write!(f, "{:?}", self)
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl std::error::Error for InsertCheckpointError {}
    +
    +/// Represents an update failure of [`SparseChain`].
    +#[derive(Clone, Debug, PartialEq)]
    +pub enum UpdateError<P = TxHeight> {
    +    /// The update cannot be applied to the chain because the chain suffix it represents did not
    +    /// connect to the existing chain. This error case contains the checkpoint height to include so
    +    /// that the chains can connect.
    +    NotConnected(u32),
    +    /// The update contains inconsistent tx states (e.g. it changed the transaction's height). This
    +    /// error is usually the inconsistency found.
    +    TxInconsistent {
    +        txid: Txid,
    +        original_pos: P,
    +        update_pos: P,
    +    },
    +}
    +
    +impl<P: core::fmt::Debug> core::fmt::Display for UpdateError<P> {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            Self::NotConnected(h) =>
    +                write!(f, "the checkpoints in the update could not be connected to the checkpoints in the chain, try include checkpoint of height {} to connect",
    +                    h),
    +            Self::TxInconsistent { txid, original_pos, update_pos } =>
    +                write!(f, "tx ({}) had position ({:?}), but is ({:?}) in the update",
    +                    txid, original_pos, update_pos),
    +        }
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl<P: core::fmt::Debug> std::error::Error for UpdateError<P> {}
    +
    +impl<P: ChainPosition> SparseChain<P> {
    +    /// Creates a new chain from a list of block hashes and heights. The caller must guarantee they
    +    /// are in the same chain.
    +    pub fn from_checkpoints<C>(checkpoints: C) -> Self
    +    where
    +        C: IntoIterator<Item = BlockId>,
    +    {
    +        Self {
    +            checkpoints: checkpoints
    +                .into_iter()
    +                .map(|block_id| block_id.into())
    +                .collect(),
    +            ..Default::default()
    +        }
    +    }
    +
    +    /// Get the checkpoint for the last known tip.
    +    pub fn latest_checkpoint(&self) -> Option<BlockId> {
    +        self.checkpoints
    +            .iter()
    +            .last()
    +            .map(|(&height, &hash)| BlockId { height, hash })
    +    }
    +
    +    /// Get the checkpoint at the given height if it exists.
    +    pub fn checkpoint_at(&self, height: u32) -> Option<BlockId> {
    +        self.checkpoints
    +            .get(&height)
    +            .map(|&hash| BlockId { height, hash })
    +    }
    +
    +    /// Return the [`ChainPosition`] of a `txid`.
    +    ///
    +    /// This returns [`None`] if the transation does not exist.
    +    pub fn tx_position(&self, txid: Txid) -> Option<&P> {
    +        self.txid_to_pos.get(&txid)
    +    }
    +
    +    /// Return a [`BTreeMap`] of all checkpoints (block hashes by height).
    +    pub fn checkpoints(&self) -> &BTreeMap<u32, BlockHash> {
    +        &self.checkpoints
    +    }
    +
    +    /// Return an iterator over checkpoints in a height range, in ascending height order.
    +    pub fn range_checkpoints(
    +        &self,
    +        range: impl RangeBounds<u32>,
    +    ) -> impl DoubleEndedIterator<Item = BlockId> + '_ {
    +        self.checkpoints
    +            .range(range)
    +            .map(|(&height, &hash)| BlockId { height, hash })
    +    }
    +
    +    /// Preview changes of updating [`Self`] with another chain that connects to it.
    +    ///
    +    /// If the `update` wishes to introduce confirmed transactions, it must contain a checkpoint
    +    /// that is exactly the same height as one of `self`'s checkpoints.
    +    ///
    +    /// To invalidate from a given checkpoint, `update` must contain a checkpoint of the same height
    +    /// but different hash. Invalidated checkpoints result in invalidated transactions becoming
    +    /// "unconfirmed".
    +    ///
    +    /// An error will be returned if an update will result in inconsistencies or if the update does
    +    /// not properly connect with `self`.
    +    ///
    +    /// Refer to [module-level documentation] for more.
    +    ///
    +    /// [module-level documentation]: crate::sparse_chain
    +    pub fn determine_changeset(&self, update: &Self) -> Result<ChangeSet<P>, UpdateError<P>> {
    +        let agreement_point = update
    +            .checkpoints
    +            .iter()
    +            .rev()
    +            .find(|&(height, hash)| self.checkpoints.get(height) == Some(hash))
    +            .map(|(&h, _)| h);
    +
    +        let last_update_cp = update.checkpoints.iter().last().map(|(&h, _)| h);
    +
    +        // the lower bound of the invalidation range
    +        let invalid_lb = if last_update_cp.is_none() || last_update_cp == agreement_point {
    +            // if agreement point is the last update checkpoint, or there is no update checkpoints,
    +            // no invalidation is required
    +            u32::MAX
    +        } else {
    +            agreement_point.map(|h| h + 1).unwrap_or(0)
    +        };
    +
    +        // the first checkpoint of the sparsechain to invalidate (if any)
    +        let invalid_from = self.checkpoints.range(invalid_lb..).next().map(|(&h, _)| h);
    +
    +        // the first checkpoint to invalidate (if any) should be represented in the update
    +        if let Some(first_invalid) = invalid_from {
    +            if !update.checkpoints.contains_key(&first_invalid) {
    +                return Err(UpdateError::NotConnected(first_invalid));
    +            }
    +        }
    +
    +        for (&txid, update_pos) in &update.txid_to_pos {
    +            // ensure all currently confirmed txs are still at the same height (unless they are
    +            // within invalidation range, or to be confirmed)
    +            if let Some(original_pos) = &self.txid_to_pos.get(&txid) {
    +                if original_pos.height() < TxHeight::Confirmed(invalid_lb)
    +                    && original_pos != &update_pos
    +                {
    +                    return Err(UpdateError::TxInconsistent {
    +                        txid,
    +                        original_pos: P::clone(original_pos),
    +                        update_pos: update_pos.clone(),
    +                    });
    +                }
    +            }
    +        }
    +
    +        // create initial change-set, based on checkpoints and txids that are to be "invalidated"
    +        let mut changeset = invalid_from
    +            .map(|from_height| self.invalidate_checkpoints_preview(from_height))
    +            .unwrap_or_default();
    +
    +        for (&height, &new_hash) in &update.checkpoints {
    +            let original_hash = self.checkpoints.get(&height).cloned();
    +
    +            let update_hash = *changeset
    +                .checkpoints
    +                .entry(height)
    +                .and_modify(|change| *change = Some(new_hash))
    +                .or_insert_with(|| Some(new_hash));
    +
    +            if original_hash == update_hash {
    +                changeset.checkpoints.remove(&height);
    +            }
    +        }
    +
    +        for (txid, new_pos) in &update.txid_to_pos {
    +            let original_pos = self.txid_to_pos.get(txid).cloned();
    +
    +            let update_pos = changeset
    +                .txids
    +                .entry(*txid)
    +                .and_modify(|change| *change = Some(new_pos.clone()))
    +                .or_insert_with(|| Some(new_pos.clone()));
    +
    +            if original_pos == *update_pos {
    +                changeset.txids.remove(txid);
    +            }
    +        }
    +
    +        Ok(changeset)
    +    }
    +
    +    /// Updates [`SparseChain`] with another chain that connects to it.
    +    ///
    +    /// This is equivilant to calling [`determine_changeset`] and [`apply_changeset`] in sequence.
    +    ///
    +    /// [`determine_changeset`]: Self::determine_changeset
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    pub fn apply_update(&mut self, update: Self) -> Result<ChangeSet<P>, UpdateError<P>> {
    +        let changeset = self.determine_changeset(&update)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    pub fn apply_changeset(&mut self, changeset: ChangeSet<P>) {
    +        for (height, update_hash) in changeset.checkpoints {
    +            let _original_hash = match update_hash {
    +                Some(update_hash) => self.checkpoints.insert(height, update_hash),
    +                None => self.checkpoints.remove(&height),
    +            };
    +        }
    +
    +        for (txid, update_pos) in changeset.txids {
    +            let original_pos = self.txid_to_pos.remove(&txid);
    +
    +            if let Some(pos) = original_pos {
    +                self.ordered_txids.remove(&(pos, txid));
    +            }
    +
    +            if let Some(pos) = update_pos {
    +                self.txid_to_pos.insert(txid, pos.clone());
    +                self.ordered_txids.insert((pos.clone(), txid));
    +            }
    +        }
    +
    +        self.prune_checkpoints();
    +    }
    +
    +    /// Derives a [`ChangeSet`] that assumes that there are no preceding changesets.
    +    ///
    +    /// The changeset returned will record additions of all [`Txid`]s and checkpoints included in
    +    /// [`Self`].
    +    pub fn initial_changeset(&self) -> ChangeSet<P> {
    +        ChangeSet {
    +            checkpoints: self
    +                .checkpoints
    +                .iter()
    +                .map(|(height, hash)| (*height, Some(*hash)))
    +                .collect(),
    +            txids: self
    +                .ordered_txids
    +                .iter()
    +                .map(|(pos, txid)| (*txid, Some(pos.clone())))
    +                .collect(),
    +        }
    +    }
    +
    +    /// Determines the [`ChangeSet`] when checkpoints `from_height` (inclusive) and above are
    +    /// invalidated. Displaced [`Txid`]s will be repositioned to [`TxHeight::Unconfirmed`].
    +    pub fn invalidate_checkpoints_preview(&self, from_height: u32) -> ChangeSet<P> {
    +        ChangeSet::<P> {
    +            checkpoints: self
    +                .checkpoints
    +                .range(from_height..)
    +                .map(|(height, _)| (*height, None))
    +                .collect(),
    +            // invalidated transactions become unconfirmed
    +            txids: self
    +                .range_txids_by_height(TxHeight::Confirmed(from_height)..TxHeight::Unconfirmed)
    +                .map(|(_, txid)| (*txid, Some(P::max_ord_of_height(TxHeight::Unconfirmed))))
    +                .collect(),
    +        }
    +    }
    +
    +    /// Invalidate checkpoints `from_height` (inclusive) and above.
    +    ///
    +    /// This is equivalent to calling [`invalidate_checkpoints_preview`] and [`apply_changeset`] in
    +    /// sequence.
    +    ///
    +    /// [`invalidate_checkpoints_preview`]: Self::invalidate_checkpoints_preview
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    pub fn invalidate_checkpoints(&mut self, from_height: u32) -> ChangeSet<P> {
    +        let changeset = self.invalidate_checkpoints_preview(from_height);
    +        self.apply_changeset(changeset.clone());
    +        changeset
    +    }
    +
    +    /// Determines the [`ChangeSet`] when all transactions of height [`TxHeight::Unconfirmed`] are
    +    /// removed completely.
    +    pub fn clear_mempool_preview(&self) -> ChangeSet<P> {
    +        let mempool_range = &(
    +            P::min_ord_of_height(TxHeight::Unconfirmed),
    +            Txid::all_zeros(),
    +        )..;
    +
    +        let txids = self
    +            .ordered_txids
    +            .range(mempool_range)
    +            .map(|(_, txid)| (*txid, None))
    +            .collect();
    +
    +        ChangeSet::<P> {
    +            txids,
    +            ..Default::default()
    +        }
    +    }
    +
    +    /// Clears all transactions of height [`TxHeight::Unconfirmed`].
    +    ///
    +    /// This is equivalent to calling [`clear_mempool_preview`] and [`apply_changeset`] in sequence.
    +    ///
    +    /// [`clear_mempool_preview`]: Self::clear_mempool_preview
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    /// [`ChangeSet`].
    +    pub fn clear_mempool(&mut self) -> ChangeSet<P> {
    +        let changeset = self.clear_mempool_preview();
    +        self.apply_changeset(changeset.clone());
    +        changeset
    +    }
    +
    +    /// Determines the resultant [`ChangeSet`] if [`Txid`] was inserted at position `pos`.
    +    ///
    +    /// Changes to the [`Txid`]'s position is allowed (under the rules noted in
    +    /// [module-level documentation]) and will be reflected in the [`ChangeSet`].
    +    ///
    +    /// [module-level documentation]: crate::sparse_chain
    +    pub fn insert_tx_preview(&self, txid: Txid, pos: P) -> Result<ChangeSet<P>, InsertTxError<P>> {
    +        let mut update = Self::default();
    +
    +        if let Some(block_id) = self.latest_checkpoint() {
    +            let _old_hash = update.checkpoints.insert(block_id.height, block_id.hash);
    +            debug_assert!(_old_hash.is_none());
    +        }
    +
    +        let tip_height = self.checkpoints.iter().last().map(|(h, _)| *h);
    +        if let TxHeight::Confirmed(tx_height) = pos.height() {
    +            if Some(tx_height) > tip_height {
    +                return Err(InsertTxError::TxTooHigh {
    +                    txid,
    +                    tx_height,
    +                    tip_height,
    +                });
    +            }
    +        }
    +
    +        let _old_pos = update.txid_to_pos.insert(txid, pos.clone());
    +        debug_assert!(_old_pos.is_none());
    +
    +        let _inserted = update.ordered_txids.insert((pos, txid));
    +        debug_assert!(_inserted, "must insert tx");
    +
    +        match self.determine_changeset(&update) {
    +            Ok(changeset) => Ok(changeset),
    +            Err(UpdateError::NotConnected(_)) => panic!("should always connect"),
    +            Err(UpdateError::TxInconsistent {
    +                txid: inconsistent_txid,
    +                original_pos,
    +                update_pos,
    +            }) => Err(InsertTxError::TxMovedUnexpectedly {
    +                txid: inconsistent_txid,
    +                original_pos,
    +                update_pos,
    +            }),
    +        }
    +    }
    +
    +    /// Inserts a given [`Txid`] at `pos`.
    +    ///
    +    /// This is equivilant to calling [`insert_tx_preview`] and [`apply_changeset`] in sequence.
    +    ///
    +    /// [`insert_tx_preview`]: Self::insert_tx_preview
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    pub fn insert_tx(&mut self, txid: Txid, pos: P) -> Result<ChangeSet<P>, InsertTxError<P>> {
    +        let changeset = self.insert_tx_preview(txid, pos)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Determines the resultant [`ChangeSet`] if [`BlockId`] was inserted.
    +    ///
    +    /// If the change would result in a change in block hash of a certain height, insertion would
    +    /// fail.
    +    pub fn insert_checkpoint_preview(
    +        &self,
    +        block_id: BlockId,
    +    ) -> Result<ChangeSet<P>, InsertCheckpointError> {
    +        let mut update = Self::default();
    +
    +        if let Some(block_id) = self.latest_checkpoint() {
    +            let _old_hash = update.checkpoints.insert(block_id.height, block_id.hash);
    +            debug_assert!(_old_hash.is_none());
    +        }
    +
    +        if let Some(original_hash) = update.checkpoints.insert(block_id.height, block_id.hash) {
    +            if original_hash != block_id.hash {
    +                return Err(InsertCheckpointError::HashNotMatching {
    +                    height: block_id.height,
    +                    original_hash,
    +                    update_hash: block_id.hash,
    +                });
    +            }
    +        }
    +
    +        match self.determine_changeset(&update) {
    +            Ok(changeset) => Ok(changeset),
    +            Err(UpdateError::NotConnected(_)) => panic!("error should have caught above"),
    +            Err(UpdateError::TxInconsistent { .. }) => panic!("should never add txs"),
    +        }
    +    }
    +
    +    /// Insert a checkpoint ([`BlockId`]).
    +    ///
    +    /// This is equivilant to calling [`insert_checkpoint_preview`] and [`apply_changeset`] in
    +    /// sequence.
    +    ///
    +    /// [`insert_checkpoint_preview`]: Self::insert_checkpoint_preview
    +    /// [`apply_changeset`]: Self::apply_changeset
    +    pub fn insert_checkpoint(
    +        &mut self,
    +        block_id: BlockId,
    +    ) -> Result<ChangeSet<P>, InsertCheckpointError> {
    +        let changeset = self.insert_checkpoint_preview(block_id)?;
    +        self.apply_changeset(changeset.clone());
    +        Ok(changeset)
    +    }
    +
    +    /// Iterate over all [`Txid`]s ordered by their [`ChainPosition`].
    +    pub fn txids(&self) -> impl DoubleEndedIterator<Item = &(P, Txid)> + ExactSizeIterator + '_ {
    +        self.ordered_txids.iter()
    +    }
    +
    +    /// Iterate over a sub-range of positioned [`Txid`]s.
    +    pub fn range_txids<R>(&self, range: R) -> impl DoubleEndedIterator<Item = &(P, Txid)> + '_
    +    where
    +        R: RangeBounds<(P, Txid)>,
    +    {
    +        let map_bound = |b: Bound<&(P, Txid)>| match b {
    +            Bound::Included((pos, txid)) => Bound::Included((pos.clone(), *txid)),
    +            Bound::Excluded((pos, txid)) => Bound::Excluded((pos.clone(), *txid)),
    +            Bound::Unbounded => Bound::Unbounded,
    +        };
    +
    +        self.ordered_txids
    +            .range((map_bound(range.start_bound()), map_bound(range.end_bound())))
    +    }
    +
    +    /// Iterate over a sub-range of positioned [`Txid`]s, where the range is defined by
    +    /// [`ChainPosition`] only.
    +    pub fn range_txids_by_position<R>(
    +        &self,
    +        range: R,
    +    ) -> impl DoubleEndedIterator<Item = &(P, Txid)> + '_
    +    where
    +        R: RangeBounds<P>,
    +    {
    +        let map_bound = |b: Bound<&P>, inc: Txid, exc: Txid| match b {
    +            Bound::Included(pos) => Bound::Included((pos.clone(), inc)),
    +            Bound::Excluded(pos) => Bound::Excluded((pos.clone(), exc)),
    +            Bound::Unbounded => Bound::Unbounded,
    +        };
    +
    +        self.ordered_txids.range((
    +            map_bound(range.start_bound(), min_txid(), max_txid()),
    +            map_bound(range.end_bound(), max_txid(), min_txid()),
    +        ))
    +    }
    +
    +    /// Iterate over a sub-range of positioned [`Txid`]s, where the range is define by [`TxHeight`]
    +    /// only.
    +    pub fn range_txids_by_height<R>(
    +        &self,
    +        range: R,
    +    ) -> impl DoubleEndedIterator<Item = &(P, Txid)> + '_
    +    where
    +        R: RangeBounds<TxHeight>,
    +    {
    +        let ord_it = |height, is_max| match is_max {
    +            true => P::max_ord_of_height(height),
    +            false => P::min_ord_of_height(height),
    +        };
    +
    +        let map_bound = |b: Bound<&TxHeight>, inc: (bool, Txid), exc: (bool, Txid)| match b {
    +            Bound::Included(&h) => Bound::Included((ord_it(h, inc.0), inc.1)),
    +            Bound::Excluded(&h) => Bound::Excluded((ord_it(h, exc.0), exc.1)),
    +            Bound::Unbounded => Bound::Unbounded,
    +        };
    +
    +        self.ordered_txids.range((
    +            map_bound(range.start_bound(), (false, min_txid()), (true, max_txid())),
    +            map_bound(range.end_bound(), (true, max_txid()), (false, min_txid())),
    +        ))
    +    }
    +
    +    /// Attempt to retrieve a [`FullTxOut`] of the given `outpoint`.
    +    ///
    +    /// This will return `Some` only if the output's transaction is in both `self` and `graph`.
    +    pub fn full_txout(&self, graph: &TxGraph, outpoint: OutPoint) -> Option<FullTxOut<P>> {
    +        let chain_pos = self.tx_position(outpoint.txid)?;
    +
    +        let tx = graph.get_tx(outpoint.txid)?;
    +        let is_on_coinbase = tx.is_coin_base();
    +        let txout = tx.output.get(outpoint.vout as usize)?.clone();
    +
    +        let spent_by = self
    +            .spent_by(graph, outpoint)
    +            .map(|(pos, txid)| (pos.clone(), txid));
    +
    +        Some(FullTxOut {
    +            outpoint,
    +            txout,
    +            chain_position: chain_pos.clone(),
    +            spent_by,
    +            is_on_coinbase,
    +        })
    +    }
    +
    +    /// Returns the value set as the checkpoint limit.
    +    ///
    +    /// Refer to [`set_checkpoint_limit`].
    +    ///
    +    /// [`set_checkpoint_limit`]: Self::set_checkpoint_limit
    +    pub fn checkpoint_limit(&self) -> Option<usize> {
    +        self.checkpoint_limit
    +    }
    +
    +    /// Set the checkpoint limit.
    +    ///
    +    /// The checkpoint limit restricts the number of checkpoints that can be stored in [`Self`].
    +    /// Oldest checkpoints are pruned first.
    +    pub fn set_checkpoint_limit(&mut self, limit: Option<usize>) {
    +        self.checkpoint_limit = limit;
    +        self.prune_checkpoints();
    +    }
    +
    +    /// Return [`Txid`]s that would be added to the sparse chain if this `changeset` was applied.
    +    pub fn changeset_additions<'a>(
    +        &'a self,
    +        changeset: &'a ChangeSet<P>,
    +    ) -> impl Iterator<Item = Txid> + 'a {
    +        changeset
    +            .txids
    +            .iter()
    +            .filter(move |(&txid, pos)| {
    +                pos.is_some() /*it was not a deletion*/ &&
    +                self.tx_position(txid).is_none() /* we don't have the txid already */
    +            })
    +            .map(|(&txid, _)| txid)
    +    }
    +
    +    fn prune_checkpoints(&mut self) -> Option<BTreeMap<u32, BlockHash>> {
    +        let limit = self.checkpoint_limit?;
    +
    +        // find last height to be pruned
    +        let last_height = *self.checkpoints.keys().rev().nth(limit)?;
    +        // first height to be kept
    +        let keep_height = last_height + 1;
    +
    +        let mut split = self.checkpoints.split_off(&keep_height);
    +        core::mem::swap(&mut self.checkpoints, &mut split);
    +
    +        Some(split)
    +    }
    +
    +    /// Finds the transaction in the chain that spends `outpoint`.
    +    ///
    +    /// [`TxGraph`] is used to provide the spend relationships.
    +    ///
    +    /// Note that the transaction including `outpoint` does not need to be in the `graph` or the
    +    /// `chain` for this to return `Some`.
    +    pub fn spent_by(&self, graph: &TxGraph, outpoint: OutPoint) -> Option<(&P, Txid)> {
    +        graph
    +            .outspends(outpoint)
    +            .iter()
    +            .find_map(|&txid| Some((self.tx_position(txid)?, txid)))
    +    }
    +
    +    /// Returns whether the sparse chain contains any checkpoints or transactions.
    +    pub fn is_empty(&self) -> bool {
    +        self.checkpoints.is_empty() && self.txid_to_pos.is_empty()
    +    }
    +}
    +
    +/// The return value of [`determine_changeset`].
    +///
    +/// [`determine_changeset`]: SparseChain::determine_changeset.
    +#[derive(Debug, Clone, PartialEq)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(crate = "serde_crate")
    +)]
    +#[must_use]
    +pub struct ChangeSet<P = TxHeight> {
    +    pub checkpoints: BTreeMap<u32, Option<BlockHash>>,
    +    pub txids: BTreeMap<Txid, Option<P>>,
    +}
    +
    +impl<I> Default for ChangeSet<I> {
    +    fn default() -> Self {
    +        Self {
    +            checkpoints: Default::default(),
    +            txids: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<P> ChangeSet<P> {
    +    /// Appends the changes in `other` into self such that applying `self` afterwards has the same
    +    /// effect as sequentially applying the original `self` and `other`.
    +    pub fn append(&mut self, mut other: Self)
    +    where
    +        P: ChainPosition,
    +    {
    +        self.checkpoints.append(&mut other.checkpoints);
    +        self.txids.append(&mut other.txids);
    +    }
    +
    +    /// Whether this changeset contains no changes.
    +    pub fn is_empty(&self) -> bool {
    +        self.checkpoints.is_empty() && self.txids.is_empty()
    +    }
    +}
    +
    +fn min_txid() -> Txid {
    +    Txid::from_inner([0x00; 32])
    +}
    +
    +fn max_txid() -> Txid {
    +    Txid::from_inner([0xff; 32])
    +}
    +
    +/// Represents an position in which transactions are ordered in [`SparseChain`].
    +///
    +/// [`ChainPosition`] implementations must be [`Ord`] by [`TxHeight`] first.
    +pub trait ChainPosition:
    +    core::fmt::Debug + Clone + Eq + PartialOrd + Ord + core::hash::Hash + Send + Sync + 'static
    +{
    +    /// Get the transaction height of the positon.
    +    fn height(&self) -> TxHeight;
    +
    +    /// Get the positon's upper bound of a given height.
    +    fn max_ord_of_height(height: TxHeight) -> Self;
    +
    +    /// Get the position's lower bound of a given height.
    +    fn min_ord_of_height(height: TxHeight) -> Self;
    +
    +    /// Get the unconfirmed position.
    +    fn unconfirmed() -> Self {
    +        Self::max_ord_of_height(TxHeight::Unconfirmed)
    +    }
    +}
    +
    +#[cfg(test)]
    +pub mod verify_chain_position {
    +    use crate::{sparse_chain::ChainPosition, ConfirmationTime, TxHeight};
    +    use alloc::vec::Vec;
    +
    +    pub fn verify_chain_position<P: ChainPosition>(head_count: u32, tail_count: u32) {
    +        let values = (0..head_count)
    +            .chain(u32::MAX - tail_count..u32::MAX)
    +            .flat_map(|i| {
    +                [
    +                    P::min_ord_of_height(TxHeight::Confirmed(i)),
    +                    P::max_ord_of_height(TxHeight::Confirmed(i)),
    +                ]
    +            })
    +            .chain([
    +                P::min_ord_of_height(TxHeight::Unconfirmed),
    +                P::max_ord_of_height(TxHeight::Unconfirmed),
    +            ])
    +            .collect::<Vec<_>>();
    +
    +        for i in 0..values.len() {
    +            for j in 0..values.len() {
    +                if i == j {
    +                    assert_eq!(values[i], values[j]);
    +                }
    +                if i < j {
    +                    assert!(values[i] <= values[j]);
    +                }
    +                if i > j {
    +                    assert!(values[i] >= values[j]);
    +                }
    +            }
    +        }
    +    }
    +
    +    #[test]
    +    fn verify_tx_height() {
    +        verify_chain_position::<TxHeight>(1000, 1000);
    +    }
    +
    +    #[test]
    +    fn verify_confirmation_time() {
    +        verify_chain_position::<ConfirmationTime>(1000, 1000);
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/spk_txout_index.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/spk_txout_index.rs.html new file mode 100644 index 0000000000..fb38a4bfdf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/spk_txout_index.rs.html @@ -0,0 +1,620 @@ +spk_txout_index.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +
    use core::ops::RangeBounds;
    +
    +use crate::{
    +    collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap},
    +    ForEachTxOut,
    +};
    +use bitcoin::{self, OutPoint, Script, Transaction, TxOut, Txid};
    +
    +/// An index storing [`TxOut`]s that have a script pubkey that matches those in a list.
    +///
    +/// The basic idea is that you insert script pubkeys you care about into the index with
    +/// [`insert_spk`] and then when you call [`scan`] the index will look at any txouts you pass in and
    +/// store and index any txouts matching one of its script pubkeys.
    +///
    +/// Each script pubkey is associated with a application defined index script index `I` which must be
    +/// [`Ord`]. Usually this is used to associate the derivation index of the script pubkey or even a
    +/// combination of `(keychain, derivation_index)`.
    +///
    +/// Note there is no harm in scanning transactions that disappear from the blockchain or were never
    +/// in there in the first place. `SpkTxOutIndex` is intentionally *monotone* -- you cannot delete or
    +/// modify txouts that have been indexed. To find out which txouts from the index are actually in the
    +/// chain or unspent etc you must use other sources of information like a [`SparseChain`].
    +///
    +/// [`TxOut`]: bitcoin::TxOut
    +/// [`insert_spk`]: Self::insert_spk
    +/// [`Ord`]: core::cmp::Ord
    +/// [`scan`]: Self::scan
    +/// [`SparseChain`]: crate::sparse_chain::SparseChain
    +#[derive(Clone, Debug)]
    +pub struct SpkTxOutIndex<I> {
    +    /// script pubkeys ordered by index
    +    spks: BTreeMap<I, Script>,
    +    /// A reverse lookup from spk to spk index
    +    spk_indices: HashMap<Script, I>,
    +    /// The set of unused indexes.
    +    unused: BTreeSet<I>,
    +    /// Lookup index and txout by outpoint.
    +    txouts: BTreeMap<OutPoint, (I, TxOut)>,
    +    /// Lookup from spk index to outpoints that had that spk
    +    spk_txouts: BTreeSet<(I, OutPoint)>,
    +}
    +
    +impl<I> Default for SpkTxOutIndex<I> {
    +    fn default() -> Self {
    +        Self {
    +            txouts: Default::default(),
    +            spks: Default::default(),
    +            spk_indices: Default::default(),
    +            spk_txouts: Default::default(),
    +            unused: Default::default(),
    +        }
    +    }
    +}
    +
    +/// This macro is used instead of a member function of `SpkTxOutIndex` which would result in a
    +/// compiler error[E0521]: "borrowed data escapes out of closure" when we attempt to take a
    +/// reference out of the `FprEachTxOut` closure during scanning.
    +macro_rules! scan_txout {
    +    ($self:ident, $op:expr, $txout:expr) => {{
    +        let spk_i = $self.spk_indices.get(&$txout.script_pubkey);
    +        if let Some(spk_i) = spk_i {
    +            $self.txouts.insert($op, (spk_i.clone(), $txout.clone()));
    +            $self.spk_txouts.insert((spk_i.clone(), $op));
    +            $self.unused.remove(&spk_i);
    +        }
    +        spk_i
    +    }};
    +}
    +
    +impl<I: Clone + Ord> SpkTxOutIndex<I> {
    +    /// Scans an object containing many txouts.
    +    ///
    +    /// Typically this is used in two situations:
    +    ///
    +    /// 1. After loading transaction data from disk you may scan over all the txouts to restore all
    +    /// your txouts.
    +    /// 2. When getting new data from the chain you usually scan it before incorporating it into your chain state.
    +    ///
    +    /// See [`ForEachTxout`] for the types that support this.
    +    ///
    +    /// [`ForEachTxout`]: crate::ForEachTxOut
    +    pub fn scan(&mut self, txouts: &impl ForEachTxOut) -> BTreeSet<I> {
    +        let mut scanned_indices = BTreeSet::new();
    +
    +        txouts.for_each_txout(|(op, txout)| {
    +            if let Some(spk_i) = scan_txout!(self, op, txout) {
    +                scanned_indices.insert(spk_i.clone());
    +            }
    +        });
    +
    +        scanned_indices
    +    }
    +
    +    /// Scan a single `TxOut` for a matching script pubkey, and returns the index that matched the
    +    /// script pubkey (if any).
    +    pub fn scan_txout(&mut self, op: OutPoint, txout: &TxOut) -> Option<&I> {
    +        scan_txout!(self, op, txout)
    +    }
    +
    +    /// Iterate over all known txouts that spend to tracked script pubkeys.
    +    pub fn txouts(
    +        &self,
    +    ) -> impl DoubleEndedIterator<Item = (&I, OutPoint, &TxOut)> + ExactSizeIterator {
    +        self.txouts
    +            .iter()
    +            .map(|(op, (index, txout))| (index, *op, txout))
    +    }
    +
    +    /// Finds all txouts on a transaction that has previously been scanned and indexed.
    +    pub fn txouts_in_tx(
    +        &self,
    +        txid: Txid,
    +    ) -> impl DoubleEndedIterator<Item = (&I, OutPoint, &TxOut)> {
    +        self.txouts
    +            .range(OutPoint::new(txid, u32::MIN)..=OutPoint::new(txid, u32::MAX))
    +            .map(|(op, (index, txout))| (index, *op, txout))
    +    }
    +
    +    /// Iterates over all outputs with script pubkeys in an index range.
    +    pub fn outputs_in_range(
    +        &self,
    +        range: impl RangeBounds<I>,
    +    ) -> impl DoubleEndedIterator<Item = (&I, OutPoint)> {
    +        use bitcoin::hashes::Hash;
    +        use core::ops::Bound::*;
    +        let min_op = OutPoint {
    +            txid: Txid::from_inner([0x00; 32]),
    +            vout: u32::MIN,
    +        };
    +        let max_op = OutPoint {
    +            txid: Txid::from_inner([0xff; 32]),
    +            vout: u32::MAX,
    +        };
    +
    +        let start = match range.start_bound() {
    +            Included(index) => Included((index.clone(), min_op)),
    +            Excluded(index) => Excluded((index.clone(), max_op)),
    +            Unbounded => Unbounded,
    +        };
    +
    +        let end = match range.end_bound() {
    +            Included(index) => Included((index.clone(), max_op)),
    +            Excluded(index) => Excluded((index.clone(), min_op)),
    +            Unbounded => Unbounded,
    +        };
    +
    +        self.spk_txouts.range((start, end)).map(|(i, op)| (i, *op))
    +    }
    +
    +    /// Returns the txout and script pubkey index of the `TxOut` at `OutPoint`.
    +    ///
    +    /// Returns `None` if the `TxOut` hasn't been scanned or if nothing matching was found there.
    +    pub fn txout(&self, outpoint: OutPoint) -> Option<(&I, &TxOut)> {
    +        self.txouts
    +            .get(&outpoint)
    +            .map(|(spk_i, txout)| (spk_i, txout))
    +    }
    +
    +    /// Returns the script that has been inserted at the `index`.
    +    ///
    +    /// If that index hasn't been inserted yet it will return `None`.
    +    pub fn spk_at_index(&self, index: &I) -> Option<&Script> {
    +        self.spks.get(index)
    +    }
    +
    +    /// The script pubkeys being tracked by the index.
    +    pub fn all_spks(&self) -> &BTreeMap<I, Script> {
    +        &self.spks
    +    }
    +
    +    /// Adds a script pubkey to scan for. Returns `false` and does nothing if spk already exists in the map
    +    ///
    +    /// the index will look for outputs spending to whenever it scans new data.
    +    pub fn insert_spk(&mut self, index: I, spk: Script) -> bool {
    +        match self.spk_indices.entry(spk.clone()) {
    +            Entry::Vacant(value) => {
    +                value.insert(index.clone());
    +                self.spks.insert(index.clone(), spk);
    +                self.unused.insert(index);
    +                true
    +            }
    +            Entry::Occupied(_) => false,
    +        }
    +    }
    +
    +    /// Iterates over a unused script pubkeys in a index range.
    +    ///
    +    /// Here "unused" means that after the script pubkey was stored in the index, the index has
    +    /// never scanned a transaction output with it.
    +    ///
    +    /// # Example
    +    ///
    +    /// ```rust
    +    /// # use bdk_chain::SpkTxOutIndex;
    +    ///
    +    /// // imagine our spks are indexed like (keychain, derivation_index).
    +    /// let txout_index = SpkTxOutIndex::<(u32, u32)>::default();
    +    /// let all_unused_spks = txout_index.unused_spks(..);
    +    /// let change_index = 1;
    +    /// let unused_change_spks =
    +    ///     txout_index.unused_spks((change_index, u32::MIN)..(change_index, u32::MAX));
    +    /// ```
    +    pub fn unused_spks<R>(&self, range: R) -> impl DoubleEndedIterator<Item = (&I, &Script)>
    +    where
    +        R: RangeBounds<I>,
    +    {
    +        self.unused
    +            .range(range)
    +            .map(move |index| (index, self.spk_at_index(index).expect("must exist")))
    +    }
    +
    +    /// Returns whether the script pubkey at `index` has been used or not.
    +    ///
    +    /// Here "unused" means that after the script pubkey was stored in the index, the index has
    +    /// never scanned a transaction output with it.
    +    pub fn is_used(&self, index: &I) -> bool {
    +        self.unused.get(index).is_none()
    +    }
    +
    +    /// Marks the script pubkey at `index` as used even though it hasn't seen an output with it.
    +    /// This only has an effect when the `index` had been added to `self` already and was unused.
    +    ///
    +    /// Returns whether the `index` was originally present as `unused`.
    +    ///
    +    /// This is useful when you want to reserve a script pubkey for something but don't want to add
    +    /// the transaction output using it to the index yet. Other callers will consider `index` used
    +    /// until you call [`unmark_used`].
    +    ///
    +    /// [`unmark_used`]: Self::unmark_used
    +    pub fn mark_used(&mut self, index: &I) -> bool {
    +        self.unused.remove(index)
    +    }
    +
    +    /// Undoes the effect of [`mark_used`]. Returns whether the `index` is inserted back into
    +    /// `unused`.
    +    ///
    +    /// Note that if `self` has scanned an output with this script pubkey then this will have no
    +    /// effect.
    +    ///
    +    /// [`mark_used`]: Self::mark_used
    +    pub fn unmark_used(&mut self, index: &I) -> bool {
    +        // we cannot set index as unused when it does not exist
    +        if !self.spks.contains_key(index) {
    +            return false;
    +        }
    +        // we cannot set index as unused when txouts are indexed under it
    +        if self.outputs_in_range(index..=index).next().is_some() {
    +            return false;
    +        }
    +        self.unused.insert(index.clone())
    +    }
    +
    +    /// Returns the index associated with the script pubkey.
    +    pub fn index_of_spk(&self, script: &Script) -> Option<&I> {
    +        self.spk_indices.get(script)
    +    }
    +
    +    /// Computes total input value going from script pubkeys in the index (sent) and total output
    +    /// value going to script pubkeys in the index (received) in `tx`. For the `sent` to be computed
    +    /// correctly the output being spent must have already been scanned by the index. Calculating
    +    /// received just uses the transaction outputs directly so will be correct even if it has not
    +    /// been scanned.
    +    pub fn sent_and_received(&self, tx: &Transaction) -> (u64, u64) {
    +        let mut sent = 0;
    +        let mut received = 0;
    +
    +        for txin in &tx.input {
    +            if let Some((_, txout)) = self.txout(txin.previous_output) {
    +                sent += txout.value;
    +            }
    +        }
    +        for txout in &tx.output {
    +            if self.index_of_spk(&txout.script_pubkey).is_some() {
    +                received += txout.value;
    +            }
    +        }
    +
    +        (sent, received)
    +    }
    +
    +    /// Computes the net value that this transaction gives to the script pubkeys in the index and
    +    /// *takes* from the transaction outputs in the index. Shorthand for calling
    +    /// [`sent_and_received`] and subtracting sent from received.
    +    ///
    +    /// [`sent_and_received`]: Self::sent_and_received
    +    pub fn net_value(&self, tx: &Transaction) -> i64 {
    +        let (sent, received) = self.sent_and_received(tx);
    +        received as i64 - sent as i64
    +    }
    +
    +    /// Whether any of the inputs of this transaction spend a txout tracked or whether any output
    +    /// matches one of our script pubkeys.
    +    ///
    +    /// It is easily possible to misuse this method and get false negatives by calling it before you
    +    /// have scanned the `TxOut`s the transaction is spending. For example if you want to filter out
    +    /// all the transactions in a block that are irrelevant you **must first scan all the
    +    /// transactions in the block** and only then use this method.
    +    pub fn is_relevant(&self, tx: &Transaction) -> bool {
    +        let input_matches = tx
    +            .input
    +            .iter()
    +            .any(|input| self.txouts.contains_key(&input.previous_output));
    +        let output_matches = tx
    +            .output
    +            .iter()
    +            .any(|output| self.spk_indices.contains_key(&output.script_pubkey));
    +        input_matches || output_matches
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/tx_data_traits.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/tx_data_traits.rs.html new file mode 100644 index 0000000000..b9d40adbad --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/tx_data_traits.rs.html @@ -0,0 +1,68 @@ +tx_data_traits.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +
    use bitcoin::{Block, OutPoint, Transaction, TxOut};
    +
    +/// Trait to do something with every txout contained in a structure.
    +///
    +/// We would prefer just work with things that can give us a `Iterator<Item=(OutPoint, &TxOut)>`
    +/// here but rust's type system makes it extremely hard to do this (without trait objects).
    +pub trait ForEachTxOut {
    +    /// The provided closure `f` will called with each `outpoint/txout` pair.
    +    fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut)));
    +}
    +
    +impl ForEachTxOut for Block {
    +    fn for_each_txout(&self, mut f: impl FnMut((OutPoint, &TxOut))) {
    +        for tx in self.txdata.iter() {
    +            tx.for_each_txout(&mut f)
    +        }
    +    }
    +}
    +
    +impl ForEachTxOut for Transaction {
    +    fn for_each_txout(&self, mut f: impl FnMut((OutPoint, &TxOut))) {
    +        let txid = self.txid();
    +        for (i, txout) in self.output.iter().enumerate() {
    +            f((
    +                OutPoint {
    +                    txid,
    +                    vout: i as u32,
    +                },
    +                txout,
    +            ))
    +        }
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/tx_graph.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/tx_graph.rs.html new file mode 100644 index 0000000000..566beb7d56 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_chain/tx_graph.rs.html @@ -0,0 +1,1164 @@ +tx_graph.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +
    //! Module for structures that store and traverse transactions.
    +//!
    +//! [`TxGraph`] is a monotone structure that inserts transactions and indexes spends. The
    +//! [`Additions`] structure reports changes of [`TxGraph`], but can also be applied on to a
    +//! [`TxGraph`] as well. Lastly, [`TxDescendants`] is an [`Iterator`] which traverses descendants of
    +//! a given transaction.
    +//!
    +//! Conflicting transactions are allowed to coexist within a [`TxGraph`]. This is useful for
    +//! identifying and traversing conflicts and descendants of a given transaction.
    +//!
    +//! # Previewing and applying changes
    +//!
    +//! Methods that either preview or apply changes to [`TxGraph`] will return [`Additions`].
    +//! [`Additions`] can be applied back on to a [`TxGraph`], or be used to inform persistent storage
    +//! of the changes to [`TxGraph`].
    +//!
    +//! ```
    +//! # use bdk_chain::tx_graph::TxGraph;
    +//! # use bdk_chain::example_utils::*;
    +//! # use bitcoin::Transaction;
    +//! # let tx_a = tx_from_hex(RAW_TX_1);
    +//! # let tx_b = tx_from_hex(RAW_TX_2);
    +//! let mut graph = TxGraph::default();
    +//!
    +//! // preview a transaction insertion (not actually inserted)
    +//! let additions = graph.insert_tx_preview(tx_a);
    +//! // apply the insertion
    +//! graph.apply_additions(additions);
    +//!
    +//! // you can also insert a transaction directly
    +//! let already_applied_additions = graph.insert_tx(tx_b);
    +//! ```
    +//!
    +//! A [`TxGraph`] can also be updated with another [`TxGraph`].
    +//!
    +//! ```
    +//! # use bdk_chain::tx_graph::TxGraph;
    +//! # use bdk_chain::example_utils::*;
    +//! # use bitcoin::Transaction;
    +//! # let tx_a = tx_from_hex(RAW_TX_1);
    +//! # let tx_b = tx_from_hex(RAW_TX_2);
    +//! let mut graph = TxGraph::default();
    +//! let update = TxGraph::new(vec![tx_a, tx_b]);
    +//!
    +//! // preview additions as result of the update
    +//! let additions = graph.determine_additions(&update);
    +//! // apply the additions
    +//! graph.apply_additions(additions);
    +//!
    +//! // we can also apply the update graph directly
    +//! // the additions will be empty as we have already applied the same update above
    +//! let additions = graph.apply_update(update);
    +//! assert!(additions.is_empty());
    +//! ```
    +use crate::{collections::*, ForEachTxOut};
    +use alloc::vec::Vec;
    +use bitcoin::{OutPoint, Transaction, TxOut, Txid};
    +use core::ops::RangeInclusive;
    +
    +/// A graph of transactions and spends.
    +///
    +/// See the [module-level documentation] for more.
    +///
    +/// [module-level documentation]: crate::tx_graph
    +#[derive(Clone, Debug, PartialEq, Default)]
    +pub struct TxGraph {
    +    txs: HashMap<Txid, TxNode>,
    +    spends: BTreeMap<OutPoint, HashSet<Txid>>,
    +
    +    // This atrocity exists so that `TxGraph::outspends()` can return a reference.
    +    // FIXME: This can be removed once `HashSet::new` is a const fn.
    +    empty_outspends: HashSet<Txid>,
    +}
    +
    +/// Node of a [`TxGraph`]. This can either be a whole transaction, or a partial transaction (where
    +/// we only have select outputs).
    +#[derive(Clone, Debug, PartialEq)]
    +enum TxNode {
    +    Whole(Transaction),
    +    Partial(BTreeMap<u32, TxOut>),
    +}
    +
    +impl Default for TxNode {
    +    fn default() -> Self {
    +        Self::Partial(BTreeMap::new())
    +    }
    +}
    +
    +impl TxGraph {
    +    /// Iterate over all tx outputs known by [`TxGraph`].
    +    pub fn all_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
    +        self.txs.iter().flat_map(|(txid, tx)| match tx {
    +            TxNode::Whole(tx) => tx
    +                .output
    +                .iter()
    +                .enumerate()
    +                .map(|(vout, txout)| (OutPoint::new(*txid, vout as _), txout))
    +                .collect::<Vec<_>>(),
    +            TxNode::Partial(txouts) => txouts
    +                .iter()
    +                .map(|(vout, txout)| (OutPoint::new(*txid, *vout as _), txout))
    +                .collect::<Vec<_>>(),
    +        })
    +    }
    +
    +    /// Iterate over all full transactions in the graph.
    +    pub fn full_transactions(&self) -> impl Iterator<Item = &Transaction> {
    +        self.txs.iter().filter_map(|(_, tx)| match tx {
    +            TxNode::Whole(tx) => Some(tx),
    +            TxNode::Partial(_) => None,
    +        })
    +    }
    +
    +    /// Get a transaction by txid. This only returns `Some` for full transactions.
    +    ///
    +    /// Refer to [`get_txout`] for getting a specific [`TxOut`].
    +    ///
    +    /// [`get_txout`]: Self::get_txout
    +    pub fn get_tx(&self, txid: Txid) -> Option<&Transaction> {
    +        match self.txs.get(&txid)? {
    +            TxNode::Whole(tx) => Some(tx),
    +            TxNode::Partial(_) => None,
    +        }
    +    }
    +
    +    /// Obtains a single tx output (if any) at specified outpoint.
    +    pub fn get_txout(&self, outpoint: OutPoint) -> Option<&TxOut> {
    +        match self.txs.get(&outpoint.txid)? {
    +            TxNode::Whole(tx) => tx.output.get(outpoint.vout as usize),
    +            TxNode::Partial(txouts) => txouts.get(&outpoint.vout),
    +        }
    +    }
    +
    +    /// Returns a [`BTreeMap`] of vout to output of the provided `txid`.
    +    pub fn txouts(&self, txid: Txid) -> Option<BTreeMap<u32, &TxOut>> {
    +        Some(match self.txs.get(&txid)? {
    +            TxNode::Whole(tx) => tx
    +                .output
    +                .iter()
    +                .enumerate()
    +                .map(|(vout, txout)| (vout as u32, txout))
    +                .collect::<BTreeMap<_, _>>(),
    +            TxNode::Partial(txouts) => txouts
    +                .iter()
    +                .map(|(vout, txout)| (*vout, txout))
    +                .collect::<BTreeMap<_, _>>(),
    +        })
    +    }
    +
    +    /// Calculates the fee of a given transaction. Returns 0 if `tx` is a coinbase transaction.
    +    /// Returns `Some(_)` if we have all the `TxOut`s being spent by `tx` in the graph (either as
    +    /// the full transactions or individual txouts). If the returned value is negative then the
    +    /// transaction is invalid according to the graph.
    +    ///
    +    /// Returns `None` if we're missing an input for the tx in the graph.
    +    ///
    +    /// Note `tx` does not have to be in the graph for this to work.
    +    pub fn calculate_fee(&self, tx: &Transaction) -> Option<i64> {
    +        if tx.is_coin_base() {
    +            return Some(0);
    +        }
    +        let inputs_sum = tx
    +            .input
    +            .iter()
    +            .map(|txin| {
    +                self.get_txout(txin.previous_output)
    +                    .map(|txout| txout.value as i64)
    +            })
    +            .sum::<Option<i64>>()?;
    +
    +        let outputs_sum = tx
    +            .output
    +            .iter()
    +            .map(|txout| txout.value as i64)
    +            .sum::<i64>();
    +
    +        Some(inputs_sum - outputs_sum)
    +    }
    +}
    +
    +impl TxGraph {
    +    /// Contruct a new [`TxGraph`] from a list of transaction.
    +    pub fn new(txs: impl IntoIterator<Item = Transaction>) -> Self {
    +        let mut new = Self::default();
    +        for tx in txs.into_iter() {
    +            let _ = new.insert_tx(tx);
    +        }
    +        new
    +    }
    +    /// Inserts the given [`TxOut`] at [`OutPoint`].
    +    ///
    +    /// Note this will ignore the action if we already have the full transaction that the txout is
    +    /// alledged to be on (even if it doesn't match it!).
    +    pub fn insert_txout(&mut self, outpoint: OutPoint, txout: TxOut) -> Additions {
    +        let additions = self.insert_txout_preview(outpoint, txout);
    +        self.apply_additions(additions.clone());
    +        additions
    +    }
    +
    +    /// Inserts the given transaction into [`TxGraph`].
    +    ///
    +    /// The [`Additions`] returned will be empty if `tx` already exists.
    +    pub fn insert_tx(&mut self, tx: Transaction) -> Additions {
    +        let additions = self.insert_tx_preview(tx);
    +        self.apply_additions(additions.clone());
    +        additions
    +    }
    +
    +    /// Extends this graph with another so that `self` becomes the union of the two sets of
    +    /// transactions.
    +    ///
    +    /// The returned [`Additions`] is the set difference of `update` and `self` (transactions that
    +    /// exist in `update` but not in `self`).
    +    pub fn apply_update(&mut self, update: TxGraph) -> Additions {
    +        let additions = self.determine_additions(&update);
    +        self.apply_additions(additions.clone());
    +        additions
    +    }
    +
    +    /// Applies [`Additions`] to [`TxGraph`].
    +    pub fn apply_additions(&mut self, additions: Additions) {
    +        for tx in additions.tx {
    +            let txid = tx.txid();
    +
    +            tx.input
    +                .iter()
    +                .map(|txin| txin.previous_output)
    +                // coinbase spends are not to be counted
    +                .filter(|outpoint| !outpoint.is_null())
    +                // record spend as this tx has spent this outpoint
    +                .for_each(|outpoint| {
    +                    self.spends.entry(outpoint).or_default().insert(txid);
    +                });
    +
    +            if let Some(TxNode::Whole(old_tx)) = self.txs.insert(txid, TxNode::Whole(tx)) {
    +                debug_assert_eq!(
    +                    old_tx.txid(),
    +                    txid,
    +                    "old tx of same txid should not be different"
    +                );
    +            }
    +        }
    +
    +        for (outpoint, txout) in additions.txout {
    +            let tx_entry = self
    +                .txs
    +                .entry(outpoint.txid)
    +                .or_insert_with(TxNode::default);
    +
    +            match tx_entry {
    +                TxNode::Whole(_) => { /* do nothing since we already have full tx */ }
    +                TxNode::Partial(txouts) => {
    +                    txouts.insert(outpoint.vout, txout);
    +                }
    +            }
    +        }
    +    }
    +
    +    /// Previews the resultant [`Additions`] when [`Self`] is updated against the `update` graph.
    +    ///
    +    /// The [`Additions`] would be the set difference of `update` and `self` (transactions that
    +    /// exist in `update` but not in `self`).
    +    pub fn determine_additions(&self, update: &TxGraph) -> Additions {
    +        let mut additions = Additions::default();
    +
    +        for (&txid, update_tx) in &update.txs {
    +            if self.get_tx(txid).is_some() {
    +                continue;
    +            }
    +
    +            match update_tx {
    +                TxNode::Whole(tx) => {
    +                    if matches!(self.txs.get(&txid), None | Some(TxNode::Partial(_))) {
    +                        additions.tx.insert(tx.clone());
    +                    }
    +                }
    +                TxNode::Partial(partial) => {
    +                    for (&vout, update_txout) in partial {
    +                        let outpoint = OutPoint::new(txid, vout);
    +
    +                        if self.get_txout(outpoint) != Some(update_txout) {
    +                            additions.txout.insert(outpoint, update_txout.clone());
    +                        }
    +                    }
    +                }
    +            }
    +        }
    +
    +        additions
    +    }
    +
    +    /// Returns the resultant [`Additions`] if the given transaction is inserted. Does not actually
    +    /// mutate [`Self`].
    +    ///
    +    /// The [`Additions`] result will be empty if `tx` already existed in `self`.
    +    pub fn insert_tx_preview(&self, tx: Transaction) -> Additions {
    +        let mut update = Self::default();
    +        update.txs.insert(tx.txid(), TxNode::Whole(tx));
    +        self.determine_additions(&update)
    +    }
    +
    +    /// Returns the resultant [`Additions`] if the given `txout` is inserted at `outpoint`. Does not
    +    /// mutate `self`.
    +    ///
    +    /// The [`Additions`] result will be empty if the `outpoint` (or a full transaction containing
    +    /// the `outpoint`) already existed in `self`.
    +    pub fn insert_txout_preview(&self, outpoint: OutPoint, txout: TxOut) -> Additions {
    +        let mut update = Self::default();
    +        update.txs.insert(
    +            outpoint.txid,
    +            TxNode::Partial([(outpoint.vout, txout)].into()),
    +        );
    +        self.determine_additions(&update)
    +    }
    +}
    +
    +impl TxGraph {
    +    /// The transactions spending from this output.
    +    ///
    +    /// `TxGraph` allows conflicting transactions within the graph. Obviously the transactions in
    +    /// the returned will never be in the same blockchain.
    +    pub fn outspends(&self, outpoint: OutPoint) -> &HashSet<Txid> {
    +        self.spends.get(&outpoint).unwrap_or(&self.empty_outspends)
    +    }
    +
    +    /// Iterates over the transactions spending from `txid`.
    +    ///
    +    /// The iterator item is a union of `(vout, txid-set)` where:
    +    ///
    +    /// - `vout` is the provided `txid`'s outpoint that is being spent
    +    /// - `txid-set` is the set of txids that is spending the `vout`
    +    pub fn tx_outspends(
    +        &self,
    +        txid: Txid,
    +    ) -> impl DoubleEndedIterator<Item = (u32, &HashSet<Txid>)> + '_ {
    +        let start = OutPoint { txid, vout: 0 };
    +        let end = OutPoint {
    +            txid,
    +            vout: u32::MAX,
    +        };
    +        self.spends
    +            .range(start..=end)
    +            .map(|(outpoint, spends)| (outpoint.vout, spends))
    +    }
    +
    +    /// Iterate over all partial transactions (outputs only) in the graph.
    +    pub fn partial_transactions(&self) -> impl Iterator<Item = (Txid, &BTreeMap<u32, TxOut>)> {
    +        self.txs.iter().filter_map(|(txid, tx)| match tx {
    +            TxNode::Whole(_) => None,
    +            TxNode::Partial(partial) => Some((*txid, partial)),
    +        })
    +    }
    +
    +    /// Creates an iterator that both filters and maps descendants from the starting `txid`.
    +    ///
    +    /// The supplied closure takes in two inputs `(depth, descendant_txid)`:
    +    ///
    +    /// * `depth` is the distance between the starting `txid` and the `descendant_txid`. I.e. if the
    +    ///     descendant is spending an output of the starting `txid`, the `depth` will be 1.
    +    /// * `descendant_txid` is the descendant's txid which we are considering to walk.
    +    ///
    +    /// The supplied closure returns an `Option<T>`, allowing the caller to map each node it vists
    +    /// and decide whether to visit descendants.
    +    pub fn walk_descendants<'g, F, O>(&'g self, txid: Txid, walk_map: F) -> TxDescendants<F>
    +    where
    +        F: FnMut(usize, Txid) -> Option<O> + 'g,
    +    {
    +        TxDescendants::new_exclude_root(self, txid, walk_map)
    +    }
    +
    +    /// Creates an iterator that both filters and maps conflicting transactions (this includes
    +    /// descendants of directly-conflicting transactions, which are also considered conflicts).
    +    ///
    +    /// Refer to [`Self::walk_descendants`] for `walk_map` usage.
    +    pub fn walk_conflicts<'g, F, O>(&'g self, tx: &'g Transaction, walk_map: F) -> TxDescendants<F>
    +    where
    +        F: FnMut(usize, Txid) -> Option<O> + 'g,
    +    {
    +        let txids = self.direct_conflicts_of_tx(tx).map(|(_, txid)| txid);
    +        TxDescendants::from_multiple_include_root(self, txids, walk_map)
    +    }
    +
    +    /// Given a transaction, return an iterator of txids which directly conflict with the given
    +    /// transaction's inputs (spends). The conflicting txids are returned with the given
    +    /// transaction's vin (in which it conflicts).
    +    ///
    +    /// Note that this only returns directly conflicting txids and does not include descendants of
    +    /// those txids (which are technically also conflicting).
    +    pub fn direct_conflicts_of_tx<'g>(
    +        &'g self,
    +        tx: &'g Transaction,
    +    ) -> impl Iterator<Item = (usize, Txid)> + '_ {
    +        let txid = tx.txid();
    +        tx.input
    +            .iter()
    +            .enumerate()
    +            .filter_map(move |(vin, txin)| self.spends.get(&txin.previous_output).zip(Some(vin)))
    +            .flat_map(|(spends, vin)| core::iter::repeat(vin).zip(spends.iter().cloned()))
    +            .filter(move |(_, conflicting_txid)| *conflicting_txid != txid)
    +    }
    +
    +    /// Whether the graph has any transactions or outputs in it.
    +    pub fn is_empty(&self) -> bool {
    +        self.txs.is_empty()
    +    }
    +}
    +
    +/// A structure that represents changes to a [`TxGraph`].
    +///
    +/// It is named "additions" because [`TxGraph`] is monotone so transactions can only be added and
    +/// not removed.
    +///
    +/// Refer to [module-level documentation] for more.
    +///
    +/// [module-level documentation]: crate::tx_graph
    +#[derive(Debug, Clone, PartialEq, Default)]
    +#[cfg_attr(
    +    feature = "serde",
    +    derive(serde::Deserialize, serde::Serialize),
    +    serde(crate = "serde_crate")
    +)]
    +#[must_use]
    +pub struct Additions {
    +    pub tx: BTreeSet<Transaction>,
    +    pub txout: BTreeMap<OutPoint, TxOut>,
    +}
    +
    +impl Additions {
    +    /// Returns true if the [`Additions`] is empty (no transactions or txouts).
    +    pub fn is_empty(&self) -> bool {
    +        self.tx.is_empty() && self.txout.is_empty()
    +    }
    +
    +    /// Iterates over all outpoints contained within [`Additions`].
    +    pub fn txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
    +        self.tx
    +            .iter()
    +            .flat_map(|tx| {
    +                tx.output
    +                    .iter()
    +                    .enumerate()
    +                    .map(move |(vout, txout)| (OutPoint::new(tx.txid(), vout as _), txout))
    +            })
    +            .chain(self.txout.iter().map(|(op, txout)| (*op, txout)))
    +    }
    +
    +    /// Appends the changes in `other` into self such that applying `self` afterwards has the same
    +    /// effect as sequentially applying the original `self` and `other`.
    +    pub fn append(&mut self, mut other: Additions) {
    +        self.tx.append(&mut other.tx);
    +        self.txout.append(&mut other.txout);
    +    }
    +}
    +
    +impl AsRef<TxGraph> for TxGraph {
    +    fn as_ref(&self) -> &TxGraph {
    +        self
    +    }
    +}
    +
    +impl ForEachTxOut for Additions {
    +    fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut))) {
    +        self.txouts().for_each(f)
    +    }
    +}
    +
    +impl ForEachTxOut for TxGraph {
    +    fn for_each_txout(&self, f: impl FnMut((OutPoint, &TxOut))) {
    +        self.all_txouts().for_each(f)
    +    }
    +}
    +
    +/// An iterator that traverses transaction descendants.
    +///
    +/// This `struct` is created by the [`walk_descendants`] method of [`TxGraph`].
    +///
    +/// [`walk_descendants`]: TxGraph::walk_descendants
    +pub struct TxDescendants<'g, F> {
    +    graph: &'g TxGraph,
    +    visited: HashSet<Txid>,
    +    stack: Vec<(usize, Txid)>,
    +    filter_map: F,
    +}
    +
    +impl<'g, F> TxDescendants<'g, F> {
    +    /// Creates a `TxDescendants` that includes the starting `txid` when iterating.
    +    #[allow(unused)]
    +    pub(crate) fn new_include_root(graph: &'g TxGraph, txid: Txid, filter_map: F) -> Self {
    +        Self {
    +            graph,
    +            visited: Default::default(),
    +            stack: [(0, txid)].into(),
    +            filter_map,
    +        }
    +    }
    +
    +    /// Creates a `TxDescendants` that excludes the starting `txid` when iterating.
    +    pub(crate) fn new_exclude_root(graph: &'g TxGraph, txid: Txid, filter_map: F) -> Self {
    +        let mut descendants = Self {
    +            graph,
    +            visited: Default::default(),
    +            stack: Default::default(),
    +            filter_map,
    +        };
    +        descendants.populate_stack(1, txid);
    +        descendants
    +    }
    +
    +    /// Creates a `TxDescendants` from multiple starting transactions that includes the starting
    +    /// `txid`s when iterating.
    +    pub(crate) fn from_multiple_include_root<I>(graph: &'g TxGraph, txids: I, filter_map: F) -> Self
    +    where
    +        I: IntoIterator<Item = Txid>,
    +    {
    +        Self {
    +            graph,
    +            visited: Default::default(),
    +            stack: txids.into_iter().map(|txid| (0, txid)).collect(),
    +            filter_map,
    +        }
    +    }
    +
    +    /// Creates a `TxDescendants` from multiple starting transactions that excludes the starting
    +    /// `txid`s when iterating.
    +    #[allow(unused)]
    +    pub(crate) fn from_multiple_exclude_root<I>(graph: &'g TxGraph, txids: I, filter_map: F) -> Self
    +    where
    +        I: IntoIterator<Item = Txid>,
    +    {
    +        let mut descendants = Self {
    +            graph,
    +            visited: Default::default(),
    +            stack: Default::default(),
    +            filter_map,
    +        };
    +        for txid in txids {
    +            descendants.populate_stack(1, txid);
    +        }
    +        descendants
    +    }
    +}
    +
    +impl<'g, F> TxDescendants<'g, F> {
    +    fn populate_stack(&mut self, depth: usize, txid: Txid) {
    +        let spend_paths = self
    +            .graph
    +            .spends
    +            .range(tx_outpoint_range(txid))
    +            .flat_map(|(_, spends)| spends)
    +            .map(|&txid| (depth, txid));
    +        self.stack.extend(spend_paths);
    +    }
    +}
    +
    +impl<'g, F, O> Iterator for TxDescendants<'g, F>
    +where
    +    F: FnMut(usize, Txid) -> Option<O>,
    +{
    +    type Item = O;
    +
    +    fn next(&mut self) -> Option<Self::Item> {
    +        let (op_spends, txid, item) = loop {
    +            // we have exhausted all paths when stack is empty
    +            let (op_spends, txid) = self.stack.pop()?;
    +            // we do not want to visit the same transaction twice
    +            if self.visited.insert(txid) {
    +                // ignore paths when user filters them out
    +                if let Some(item) = (self.filter_map)(op_spends, txid) {
    +                    break (op_spends, txid, item);
    +                }
    +            }
    +        };
    +
    +        self.populate_stack(op_spends + 1, txid);
    +        Some(item)
    +    }
    +}
    +
    +fn tx_outpoint_range(txid: Txid) -> RangeInclusive<OutPoint> {
    +    OutPoint::new(txid, u32::MIN)..=OutPoint::new(txid, u32::MAX)
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/bnb.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/bnb.rs.html new file mode 100644 index 0000000000..41adf3746c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/bnb.rs.html @@ -0,0 +1,1292 @@ +bnb.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +589
    +590
    +591
    +592
    +593
    +594
    +595
    +596
    +597
    +598
    +599
    +600
    +601
    +602
    +603
    +604
    +605
    +606
    +607
    +608
    +609
    +610
    +611
    +612
    +613
    +614
    +615
    +616
    +617
    +618
    +619
    +620
    +621
    +622
    +623
    +624
    +625
    +626
    +627
    +628
    +629
    +630
    +631
    +632
    +633
    +634
    +635
    +636
    +637
    +638
    +639
    +640
    +641
    +642
    +643
    +644
    +645
    +
    use super::*;
    +
    +/// Strategy in which we should branch.
    +pub enum BranchStrategy {
    +    /// We continue exploring subtrees of this node, starting with the inclusion branch.
    +    Continue,
    +    /// We continue exploring ONY the omission branch of this node, skipping the inclusion branch.
    +    SkipInclusion,
    +    /// We skip both the inclusion and omission branches of this node.
    +    SkipBoth,
    +}
    +
    +impl BranchStrategy {
    +    pub fn will_continue(&self) -> bool {
    +        matches!(self, Self::Continue | Self::SkipInclusion)
    +    }
    +}
    +
    +/// Closure to decide the branching strategy, alongside a score (if the current selection is a
    +/// candidate solution).
    +pub type DecideStrategy<'c, S> = dyn Fn(&Bnb<'c, S>) -> (BranchStrategy, Option<S>);
    +
    +/// [`Bnb`] represents the current state of the BnB algorithm.
    +pub struct Bnb<'c, S> {
    +    pub pool: Vec<(usize, &'c WeightedValue)>,
    +    pub pool_pos: usize,
    +    pub best_score: S,
    +
    +    pub selection: CoinSelector<'c>,
    +    pub rem_abs: u64,
    +    pub rem_eff: i64,
    +}
    +
    +impl<'c, S: Ord> Bnb<'c, S> {
    +    /// Creates a new [`Bnb`].
    +    pub fn new(selector: CoinSelector<'c>, pool: Vec<(usize, &'c WeightedValue)>, max: S) -> Self {
    +        let (rem_abs, rem_eff) = pool.iter().fold((0, 0), |(abs, eff), (_, c)| {
    +            (
    +                abs + c.value,
    +                eff + c.effective_value(selector.opts.target_feerate),
    +            )
    +        });
    +
    +        Self {
    +            pool,
    +            pool_pos: 0,
    +            best_score: max,
    +            selection: selector,
    +            rem_abs,
    +            rem_eff,
    +        }
    +    }
    +
    +    /// Turns our [`Bnb`] state into an iterator.
    +    ///
    +    /// `strategy` should assess our current selection/node and determine the branching strategy and
    +    /// whether this selection is a candidate solution (if so, return the score of the selection).
    +    pub fn into_iter<'f>(self, strategy: &'f DecideStrategy<'c, S>) -> BnbIter<'c, 'f, S> {
    +        BnbIter {
    +            state: self,
    +            done: false,
    +            strategy,
    +        }
    +    }
    +
    +    /// Attempt to backtrack to the previously selected node's omission branch, return false
    +    /// otherwise (no more solutions).
    +    pub fn backtrack(&mut self) -> bool {
    +        (0..self.pool_pos).rev().any(|pos| {
    +            let (index, candidate) = self.pool[pos];
    +
    +            if self.selection.is_selected(index) {
    +                // deselect last `pos`, so next round will check omission branch
    +                self.pool_pos = pos;
    +                self.selection.deselect(index);
    +                true
    +            } else {
    +                self.rem_abs += candidate.value;
    +                self.rem_eff += candidate.effective_value(self.selection.opts.target_feerate);
    +                false
    +            }
    +        })
    +    }
    +
    +    /// Continue down this branch, skip inclusion branch if specified.
    +    pub fn forward(&mut self, skip: bool) {
    +        let (index, candidate) = self.pool[self.pool_pos];
    +        self.rem_abs -= candidate.value;
    +        self.rem_eff -= candidate.effective_value(self.selection.opts.target_feerate);
    +
    +        if !skip {
    +            self.selection.select(index);
    +        }
    +    }
    +
    +    /// Compare advertised score with current best. New best will be the smaller value. Return true
    +    /// if best is replaced.
    +    pub fn advertise_new_score(&mut self, score: S) -> bool {
    +        if score <= self.best_score {
    +            self.best_score = score;
    +            return true;
    +        }
    +        false
    +    }
    +}
    +
    +pub struct BnbIter<'c, 'f, S> {
    +    state: Bnb<'c, S>,
    +    done: bool,
    +
    +    /// Check our current selection (node), and returns the branching strategy, alongside a score
    +    /// (if the current selection is a candidate solution).
    +    strategy: &'f DecideStrategy<'c, S>,
    +}
    +
    +impl<'c, 'f, S: Ord + Copy + Display> Iterator for BnbIter<'c, 'f, S> {
    +    type Item = Option<CoinSelector<'c>>;
    +
    +    fn next(&mut self) -> Option<Self::Item> {
    +        if self.done {
    +            return None;
    +        }
    +
    +        let (strategy, score) = (self.strategy)(&self.state);
    +
    +        let mut found_best = Option::<CoinSelector>::None;
    +
    +        if let Some(score) = score {
    +            if self.state.advertise_new_score(score) {
    +                found_best = Some(self.state.selection.clone());
    +            }
    +        }
    +
    +        debug_assert!(
    +            !strategy.will_continue() || self.state.pool_pos < self.state.pool.len(),
    +            "Faulty strategy implementation! Strategy suggested that we continue traversing, however we have already reached the end of the candidates pool! pool_len={}, pool_pos={}",
    +            self.state.pool.len(), self.state.pool_pos,
    +        );
    +
    +        match strategy {
    +            BranchStrategy::Continue => {
    +                self.state.forward(false);
    +            }
    +            BranchStrategy::SkipInclusion => {
    +                self.state.forward(true);
    +            }
    +            BranchStrategy::SkipBoth => {
    +                if !self.state.backtrack() {
    +                    self.done = true;
    +                }
    +            }
    +        };
    +
    +        // increment selection pool position for next round
    +        self.state.pool_pos += 1;
    +
    +        if found_best.is_some() || !self.done {
    +            Some(found_best)
    +        } else {
    +            // we have traversed all branches
    +            None
    +        }
    +    }
    +}
    +
    +/// Determines how we should limit rounds of branch and bound.
    +pub enum BnbLimit {
    +    Rounds(usize),
    +    #[cfg(feature = "std")]
    +    Duration(core::time::Duration),
    +}
    +
    +impl From<usize> for BnbLimit {
    +    fn from(v: usize) -> Self {
    +        Self::Rounds(v)
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl From<core::time::Duration> for BnbLimit {
    +    fn from(v: core::time::Duration) -> Self {
    +        Self::Duration(v)
    +    }
    +}
    +
    +/// This is a variation of the Branch and Bound Coin Selection algorithm designed by Murch (as seen
    +/// in Bitcoin Core).
    +///
    +/// The differences are as follows:
    +/// * In additional to working with effective values, we also work with absolute values.
    +///   This way, we can use bounds of absolute values to enforce `min_absolute_fee` (which is used by
    +///   RBF), and `max_extra_target` (which can be used to increase the possible solution set, given
    +///   that the sender is okay with sending extra to the receiver).
    +///
    +/// Murch's Master Thesis: <https://murch.one/wp-content/uploads/2016/11/erhardt2016coinselection.pdf>
    +/// Bitcoin Core Implementation: <https://github.com/bitcoin/bitcoin/blob/23.x/src/wallet/coinselection.cpp#L65>
    +///
    +/// TODO: Another optimization we could do is figure out candidate with smallest waste, and
    +/// if we find a result with waste equal to this, we can just break.
    +pub fn coin_select_bnb<L>(limit: L, selector: CoinSelector) -> Option<CoinSelector>
    +where
    +    L: Into<BnbLimit>,
    +{
    +    let opts = selector.opts;
    +
    +    // prepare pool of candidates to select from:
    +    // * filter out candidates with negative/zero effective values
    +    // * sort candidates by descending effective value
    +    let pool = {
    +        let mut pool = selector
    +            .unselected()
    +            .filter(|(_, c)| c.effective_value(opts.target_feerate) > 0)
    +            .collect::<Vec<_>>();
    +        pool.sort_unstable_by(|(_, a), (_, b)| {
    +            let a = a.effective_value(opts.target_feerate);
    +            let b = b.effective_value(opts.target_feerate);
    +            b.cmp(&a)
    +        });
    +        pool
    +    };
    +
    +    let feerate_decreases = opts.target_feerate > opts.long_term_feerate();
    +
    +    let target_abs = opts.target_value.unwrap_or(0) + opts.min_absolute_fee;
    +    let target_eff = selector.effective_target();
    +
    +    let upper_bound_abs = target_abs + (opts.drain_weight as f32 * opts.target_feerate) as u64;
    +    let upper_bound_eff = target_eff + opts.drain_waste();
    +
    +    let strategy = move |bnb: &Bnb<i64>| -> (BranchStrategy, Option<i64>) {
    +        let selected_abs = bnb.selection.selected_absolute_value();
    +        let selected_eff = bnb.selection.selected_effective_value();
    +
    +        // backtrack if remaining value is not enough to reach target
    +        if selected_abs + bnb.rem_abs < target_abs || selected_eff + bnb.rem_eff < target_eff {
    +            return (BranchStrategy::SkipBoth, None);
    +        }
    +
    +        // backtrack if selected value already surpassed upper bounds
    +        if selected_abs > upper_bound_abs && selected_eff > upper_bound_eff {
    +            return (BranchStrategy::SkipBoth, None);
    +        }
    +
    +        let selected_waste = bnb.selection.selected_waste();
    +
    +        // when feerate decreases, waste without excess is guaranteed to increase with each
    +        // selection. So if we have already surpassed best score, we can backtrack.
    +        if feerate_decreases && selected_waste > bnb.best_score {
    +            return (BranchStrategy::SkipBoth, None);
    +        }
    +
    +        // solution?
    +        if selected_abs >= target_abs && selected_eff >= target_eff {
    +            let waste = selected_waste + bnb.selection.current_excess();
    +            return (BranchStrategy::SkipBoth, Some(waste));
    +        }
    +
    +        // early bailout optimization:
    +        // If the candidate at the previous position is NOT selected and has the same weight and
    +        // value as the current candidate, we can skip selecting the current candidate.
    +        if bnb.pool_pos > 0 && !bnb.selection.is_empty() {
    +            let (_, candidate) = bnb.pool[bnb.pool_pos];
    +            let (prev_index, prev_candidate) = bnb.pool[bnb.pool_pos - 1];
    +
    +            if !bnb.selection.is_selected(prev_index)
    +                && candidate.value == prev_candidate.value
    +                && candidate.weight == prev_candidate.weight
    +            {
    +                return (BranchStrategy::SkipInclusion, None);
    +            }
    +        }
    +
    +        // check out inclusion branch first
    +        (BranchStrategy::Continue, None)
    +    };
    +
    +    // determine sum of absolute and effective values for current selection
    +    let (selected_abs, selected_eff) = selector.selected().fold((0, 0), |(abs, eff), (_, c)| {
    +        (
    +            abs + c.value,
    +            eff + c.effective_value(selector.opts.target_feerate),
    +        )
    +    });
    +
    +    let bnb = Bnb::new(selector, pool, i64::MAX);
    +
    +    // not enough to select anyway
    +    if selected_abs + bnb.rem_abs < target_abs || selected_eff + bnb.rem_eff < target_eff {
    +        return None;
    +    }
    +
    +    match limit.into() {
    +        BnbLimit::Rounds(rounds) => {
    +            bnb.into_iter(&strategy)
    +                .take(rounds)
    +                .reduce(|b, c| if c.is_some() { c } else { b })
    +        }
    +        #[cfg(feature = "std")]
    +        BnbLimit::Duration(duration) => {
    +            let start = std::time::SystemTime::now();
    +            bnb.into_iter(&strategy)
    +                .take_while(|_| start.elapsed().expect("failed to get system time") <= duration)
    +                .reduce(|b, c| if c.is_some() { c } else { b })
    +        }
    +    }?
    +}
    +
    +#[cfg(all(test, feature = "miniscript"))]
    +mod test {
    +    use bitcoin::secp256k1::Secp256k1;
    +
    +    use crate::coin_select::{evaluate_cs::evaluate, ExcessStrategyKind};
    +
    +    use super::{
    +        coin_select_bnb,
    +        evaluate_cs::{Evaluation, EvaluationError},
    +        tester::Tester,
    +        CoinSelector, CoinSelectorOpt, Vec, WeightedValue,
    +    };
    +
    +    fn tester() -> Tester {
    +        const DESC_STR: &str = "tr(xprv9uBuvtdjghkz8D1qzsSXS9Vs64mqrUnXqzNccj2xcvnCHPpXKYE1U2Gbh9CDHk8UPyF2VuXpVkDA7fk5ZP4Hd9KnhUmTscKmhee9Dp5sBMK)";
    +        Tester::new(&Secp256k1::default(), DESC_STR)
    +    }
    +
    +    fn evaluate_bnb(
    +        initial_selector: CoinSelector,
    +        max_tries: usize,
    +    ) -> Result<Evaluation, EvaluationError> {
    +        evaluate(initial_selector, |cs| {
    +            coin_select_bnb(max_tries, cs.clone()).map_or(false, |new_cs| {
    +                *cs = new_cs;
    +                true
    +            })
    +        })
    +    }
    +
    +    #[test]
    +    fn not_enough_coins() {
    +        let t = tester();
    +        let candidates: Vec<WeightedValue> = vec![
    +            t.gen_candidate(0, 100_000).into(),
    +            t.gen_candidate(1, 100_000).into(),
    +        ];
    +        let opts = t.gen_opts(200_000);
    +        let selector = CoinSelector::new(&candidates, &opts);
    +        assert!(!coin_select_bnb(10_000, selector).is_some());
    +    }
    +
    +    #[test]
    +    fn exactly_enough_coins_preselected() {
    +        let t = tester();
    +        let candidates: Vec<WeightedValue> = vec![
    +            t.gen_candidate(0, 100_000).into(), // to preselect
    +            t.gen_candidate(1, 100_000).into(), // to preselect
    +            t.gen_candidate(2, 100_000).into(),
    +        ];
    +        let opts = CoinSelectorOpt {
    +            target_feerate: 0.0,
    +            ..t.gen_opts(200_000)
    +        };
    +        let selector = {
    +            let mut selector = CoinSelector::new(&candidates, &opts);
    +            selector.select(0); // preselect
    +            selector.select(1); // preselect
    +            selector
    +        };
    +
    +        let evaluation = evaluate_bnb(selector, 10_000).expect("eval failed");
    +        println!("{}", evaluation);
    +        assert_eq!(evaluation.solution.selected, (0..=1).collect());
    +        assert_eq!(evaluation.solution.excess_strategies.len(), 1);
    +        assert_eq!(
    +            evaluation.feerate_offset(ExcessStrategyKind::ToFee).floor(),
    +            0.0
    +        );
    +    }
    +
    +    /// `cost_of_change` acts as the upper-bound in Bnb, we check whether these boundaries are
    +    /// enforced in code
    +    #[test]
    +    fn cost_of_change() {
    +        let t = tester();
    +        let candidates: Vec<WeightedValue> = vec![
    +            t.gen_candidate(0, 200_000).into(),
    +            t.gen_candidate(1, 200_000).into(),
    +            t.gen_candidate(2, 200_000).into(),
    +        ];
    +
    +        // lowest and highest possible `recipient_value` opts for derived `drain_waste`, assuming
    +        // that we want 2 candidates selected
    +        let (lowest_opts, highest_opts) = {
    +            let opts = t.gen_opts(0);
    +
    +            let fee_from_inputs =
    +                (candidates[0].weight as f32 * opts.target_feerate).ceil() as u64 * 2;
    +            let fee_from_template =
    +                ((opts.base_weight + 2) as f32 * opts.target_feerate).ceil() as u64;
    +
    +            let lowest_opts = CoinSelectorOpt {
    +                target_value: Some(
    +                    400_000 - fee_from_inputs - fee_from_template - opts.drain_waste() as u64,
    +                ),
    +                ..opts
    +            };
    +
    +            let highest_opts = CoinSelectorOpt {
    +                target_value: Some(400_000 - fee_from_inputs - fee_from_template),
    +                ..opts
    +            };
    +
    +            (lowest_opts, highest_opts)
    +        };
    +
    +        // test lowest possible target we are able to select
    +        let lowest_eval = evaluate_bnb(CoinSelector::new(&candidates, &lowest_opts), 10_000);
    +        assert!(lowest_eval.is_ok());
    +        let lowest_eval = lowest_eval.unwrap();
    +        println!("LB {}", lowest_eval);
    +        assert_eq!(lowest_eval.solution.selected.len(), 2);
    +        assert_eq!(lowest_eval.solution.excess_strategies.len(), 1);
    +        assert_eq!(
    +            lowest_eval
    +                .feerate_offset(ExcessStrategyKind::ToFee)
    +                .floor(),
    +            0.0
    +        );
    +
    +        // test highest possible target we are able to select
    +        let highest_eval = evaluate_bnb(CoinSelector::new(&candidates, &highest_opts), 10_000);
    +        assert!(highest_eval.is_ok());
    +        let highest_eval = highest_eval.unwrap();
    +        println!("UB {}", highest_eval);
    +        assert_eq!(highest_eval.solution.selected.len(), 2);
    +        assert_eq!(highest_eval.solution.excess_strategies.len(), 1);
    +        assert_eq!(
    +            highest_eval
    +                .feerate_offset(ExcessStrategyKind::ToFee)
    +                .floor(),
    +            0.0
    +        );
    +
    +        // test lower out of bounds
    +        let loob_opts = CoinSelectorOpt {
    +            target_value: lowest_opts.target_value.map(|v| v - 1),
    +            ..lowest_opts
    +        };
    +        let loob_eval = evaluate_bnb(CoinSelector::new(&candidates, &loob_opts), 10_000);
    +        assert!(loob_eval.is_err());
    +        println!("Lower OOB: {}", loob_eval.unwrap_err());
    +
    +        // test upper out of bounds
    +        let uoob_opts = CoinSelectorOpt {
    +            target_value: highest_opts.target_value.map(|v| v + 1),
    +            ..highest_opts
    +        };
    +        let uoob_eval = evaluate_bnb(CoinSelector::new(&candidates, &uoob_opts), 10_000);
    +        assert!(uoob_eval.is_err());
    +        println!("Upper OOB: {}", uoob_eval.unwrap_err());
    +    }
    +
    +    #[test]
    +    fn try_select() {
    +        let t = tester();
    +        let candidates: Vec<WeightedValue> = vec![
    +            t.gen_candidate(0, 300_000).into(),
    +            t.gen_candidate(1, 300_000).into(),
    +            t.gen_candidate(2, 300_000).into(),
    +            t.gen_candidate(3, 200_000).into(),
    +            t.gen_candidate(4, 200_000).into(),
    +        ];
    +        let make_opts = |v: u64| -> CoinSelectorOpt {
    +            CoinSelectorOpt {
    +                target_feerate: 0.0,
    +                ..t.gen_opts(v)
    +            }
    +        };
    +
    +        let test_cases = vec![
    +            (make_opts(100_000), false, 0),
    +            (make_opts(200_000), true, 1),
    +            (make_opts(300_000), true, 1),
    +            (make_opts(500_000), true, 2),
    +            (make_opts(1_000_000), true, 4),
    +            (make_opts(1_200_000), false, 0),
    +            (make_opts(1_300_000), true, 5),
    +            (make_opts(1_400_000), false, 0),
    +        ];
    +
    +        for (opts, expect_solution, expect_selected) in test_cases {
    +            let res = evaluate_bnb(CoinSelector::new(&candidates, &opts), 10_000);
    +            assert_eq!(res.is_ok(), expect_solution);
    +
    +            match res {
    +                Ok(eval) => {
    +                    println!("{}", eval);
    +                    assert_eq!(eval.feerate_offset(ExcessStrategyKind::ToFee), 0.0);
    +                    assert_eq!(eval.solution.selected.len(), expect_selected as _);
    +                }
    +                Err(err) => println!("expected failure: {}", err),
    +            }
    +        }
    +    }
    +
    +    #[test]
    +    fn early_bailout_optimization() {
    +        let t = tester();
    +
    +        // target: 300_000
    +        // candidates: 2x of 125_000, 1000x of 100_000, 1x of 50_000
    +        // expected solution: 2x 125_000, 1x 50_000
    +        // set bnb max tries: 1100, should succeed
    +        let candidates = {
    +            let mut candidates: Vec<WeightedValue> = vec![
    +                t.gen_candidate(0, 125_000).into(),
    +                t.gen_candidate(1, 125_000).into(),
    +                t.gen_candidate(2, 50_000).into(),
    +            ];
    +            (3..3 + 1000_u32)
    +                .for_each(|index| candidates.push(t.gen_candidate(index, 100_000).into()));
    +            candidates
    +        };
    +        let opts = CoinSelectorOpt {
    +            target_feerate: 0.0,
    +            ..t.gen_opts(300_000)
    +        };
    +
    +        let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), 1100);
    +        assert!(result.is_ok());
    +
    +        let eval = result.unwrap();
    +        println!("{}", eval);
    +        assert_eq!(eval.solution.selected, (0..=2).collect());
    +    }
    +
    +    #[test]
    +    fn should_exhaust_iteration() {
    +        static MAX_TRIES: usize = 1000;
    +        let t = tester();
    +        let candidates = (0..MAX_TRIES + 1)
    +            .map(|index| t.gen_candidate(index as _, 10_000).into())
    +            .collect::<Vec<WeightedValue>>();
    +        let opts = t.gen_opts(10_001 * MAX_TRIES as u64);
    +        let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), MAX_TRIES);
    +        assert!(result.is_err());
    +        println!("error as expected: {}", result.unwrap_err());
    +    }
    +
    +    /// Solution should have fee >= min_absolute_fee (or no solution at all)
    +    #[test]
    +    fn min_absolute_fee() {
    +        let t = tester();
    +        let candidates = {
    +            let mut candidates = Vec::new();
    +            t.gen_weighted_values(&mut candidates, 5, 10_000);
    +            t.gen_weighted_values(&mut candidates, 5, 20_000);
    +            t.gen_weighted_values(&mut candidates, 5, 30_000);
    +            t.gen_weighted_values(&mut candidates, 10, 10_300);
    +            t.gen_weighted_values(&mut candidates, 10, 10_500);
    +            t.gen_weighted_values(&mut candidates, 10, 10_700);
    +            t.gen_weighted_values(&mut candidates, 10, 10_900);
    +            t.gen_weighted_values(&mut candidates, 10, 11_000);
    +            t.gen_weighted_values(&mut candidates, 10, 12_000);
    +            t.gen_weighted_values(&mut candidates, 10, 13_000);
    +            candidates
    +        };
    +        let mut opts = CoinSelectorOpt {
    +            min_absolute_fee: 1,
    +            ..t.gen_opts(100_000)
    +        };
    +
    +        (1..=120_u64).for_each(|fee_factor| {
    +            opts.min_absolute_fee = fee_factor * 31;
    +
    +            let result = evaluate_bnb(CoinSelector::new(&candidates, &opts), 21_000);
    +            match result {
    +                Ok(result) => {
    +                    println!("Solution {}", result);
    +                    let fee = result.solution.excess_strategies[&ExcessStrategyKind::ToFee].fee;
    +                    assert!(fee >= opts.min_absolute_fee);
    +                    assert_eq!(result.solution.excess_strategies.len(), 1);
    +                }
    +                Err(err) => {
    +                    println!("No Solution: {}", err);
    +                }
    +            }
    +        });
    +    }
    +
    +    /// For a decreasing feerate (longterm feerate is lower than effective feerate), we should
    +    /// select less. For increasing feerate (longterm feerate is higher than effective feerate), we
    +    /// should select more.
    +    #[test]
    +    fn feerate_difference() {
    +        let t = tester();
    +        let candidates = {
    +            let mut candidates = Vec::new();
    +            t.gen_weighted_values(&mut candidates, 10, 2_000);
    +            t.gen_weighted_values(&mut candidates, 10, 5_000);
    +            t.gen_weighted_values(&mut candidates, 10, 20_000);
    +            candidates
    +        };
    +
    +        let decreasing_feerate_opts = CoinSelectorOpt {
    +            target_feerate: 1.25,
    +            long_term_feerate: Some(0.25),
    +            ..t.gen_opts(100_000)
    +        };
    +
    +        let increasing_feerate_opts = CoinSelectorOpt {
    +            target_feerate: 0.25,
    +            long_term_feerate: Some(1.25),
    +            ..t.gen_opts(100_000)
    +        };
    +
    +        let decreasing_res = evaluate_bnb(
    +            CoinSelector::new(&candidates, &decreasing_feerate_opts),
    +            21_000,
    +        )
    +        .expect("no result");
    +        let decreasing_len = decreasing_res.solution.selected.len();
    +
    +        let increasing_res = evaluate_bnb(
    +            CoinSelector::new(&candidates, &increasing_feerate_opts),
    +            21_000,
    +        )
    +        .expect("no result");
    +        let increasing_len = increasing_res.solution.selected.len();
    +
    +        println!("decreasing_len: {}", decreasing_len);
    +        println!("increasing_len: {}", increasing_len);
    +        assert!(decreasing_len < increasing_len);
    +    }
    +
    +    /// TODO: UNIMPLEMENTED TESTS:
    +    /// * Excess strategies:
    +    ///     * We should always have `ExcessStrategy::ToFee`.
    +    ///     * We should only have `ExcessStrategy::ToRecipient` when `max_extra_target > 0`.
    +    ///     * We should only have `ExcessStrategy::ToDrain` when `drain_value >= min_drain_value`.
    +    /// * Fuzz
    +    ///     * Solution feerate should never be lower than target feerate
    +    ///     * Solution fee should never be lower than `min_absolute_fee`
    +    ///     * Preselected should always remain selected
    +    fn _todo() {}
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/coin_selector.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/coin_selector.rs.html new file mode 100644 index 0000000000..ab306c9abd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/coin_selector.rs.html @@ -0,0 +1,1234 @@ +coin_selector.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +589
    +590
    +591
    +592
    +593
    +594
    +595
    +596
    +597
    +598
    +599
    +600
    +601
    +602
    +603
    +604
    +605
    +606
    +607
    +608
    +609
    +610
    +611
    +612
    +613
    +614
    +615
    +616
    +
    use super::*;
    +
    +/// A [`WeightedValue`] represents an input candidate for [`CoinSelector`]. This can either be a
    +/// single UTXO, or a group of UTXOs that should be spent together.
    +#[derive(Debug, Clone, Copy)]
    +pub struct WeightedValue {
    +    /// Total value of the UTXO(s) that this [`WeightedValue`] represents.
    +    pub value: u64,
    +    /// Total weight of including this/these UTXO(s).
    +    /// `txin` fields: `prevout`, `nSequence`, `scriptSigLen`, `scriptSig`, `scriptWitnessLen`,
    +    /// `scriptWitness` should all be included.
    +    pub weight: u32,
    +    /// Total number of inputs; so we can calculate extra `varint` weight due to `vin` len changes.
    +    pub input_count: usize,
    +    /// Whether this [`WeightedValue`] contains at least one segwit spend.
    +    pub is_segwit: bool,
    +}
    +
    +impl WeightedValue {
    +    /// Create a new [`WeightedValue`] that represents a single input.
    +    ///
    +    /// `satisfaction_weight` is the weight of `scriptSigLen + scriptSig + scriptWitnessLen +
    +    /// scriptWitness`.
    +    pub fn new(value: u64, satisfaction_weight: u32, is_segwit: bool) -> WeightedValue {
    +        let weight = TXIN_BASE_WEIGHT + satisfaction_weight;
    +        WeightedValue {
    +            value,
    +            weight,
    +            input_count: 1,
    +            is_segwit,
    +        }
    +    }
    +
    +    /// Effective value of this input candidate: `actual_value - input_weight * feerate (sats/wu)`.
    +    pub fn effective_value(&self, effective_feerate: f32) -> i64 {
    +        // We prefer undershooting the candidate's effective value (so we over estimate the fee of a
    +        // candidate). If we overshoot the candidate's effective value, it may be possible to find a
    +        // solution which does not meet the target feerate.
    +        self.value as i64 - (self.weight as f32 * effective_feerate).ceil() as i64
    +    }
    +}
    +
    +#[derive(Debug, Clone, Copy)]
    +pub struct CoinSelectorOpt {
    +    /// The value we need to select.
    +    /// If the value is `None` then the selection will be complete if it can pay for the drain
    +    /// output and satisfy the other constraints (e.g. minimum fees).
    +    pub target_value: Option<u64>,
    +    /// Additional leeway for the target value.
    +    pub max_extra_target: u64, // TODO: Maybe out of scope here?
    +
    +    /// The feerate we should try and achieve in sats per weight unit.
    +    pub target_feerate: f32,
    +    /// The feerate
    +    pub long_term_feerate: Option<f32>, // TODO: Maybe out of scope? (waste)
    +    /// The minimum absolute fee. I.e. needed for RBF.
    +    pub min_absolute_fee: u64,
    +
    +    /// The weight of the template transaction including fixed fields and outputs.
    +    pub base_weight: u32,
    +    /// Additional weight if we include the drain (change) output.
    +    pub drain_weight: u32,
    +    /// Weight of spending the drain (change) output in the future.
    +    pub spend_drain_weight: u32, // TODO: Maybe out of scope? (waste)
    +
    +    /// Minimum value allowed for a drain (change) output.
    +    pub min_drain_value: u64,
    +}
    +
    +impl CoinSelectorOpt {
    +    fn from_weights(base_weight: u32, drain_weight: u32, spend_drain_weight: u32) -> Self {
    +        // 0.25 sats/wu == 1 sat/vb
    +        let target_feerate = 0.25_f32;
    +
    +        // set `min_drain_value` to dust limit
    +        let min_drain_value =
    +            3 * ((drain_weight + spend_drain_weight) as f32 * target_feerate) as u64;
    +
    +        Self {
    +            target_value: None,
    +            max_extra_target: 0,
    +            target_feerate,
    +            long_term_feerate: None,
    +            min_absolute_fee: 0,
    +            base_weight,
    +            drain_weight,
    +            spend_drain_weight,
    +            min_drain_value,
    +        }
    +    }
    +
    +    pub fn fund_outputs(
    +        txouts: &[TxOut],
    +        drain_output: &TxOut,
    +        drain_satisfaction_weight: u32,
    +    ) -> Self {
    +        let mut tx = Transaction {
    +            input: vec![],
    +            version: 1,
    +            lock_time: LockTime::ZERO.into(),
    +            output: txouts.to_vec(),
    +        };
    +        let base_weight = tx.weight();
    +        // this awkward calculation is necessary since TxOut doesn't have \.weight()
    +        let drain_weight = {
    +            tx.output.push(drain_output.clone());
    +            tx.weight() - base_weight
    +        };
    +        Self {
    +            target_value: if txouts.is_empty() {
    +                None
    +            } else {
    +                Some(txouts.iter().map(|txout| txout.value).sum())
    +            },
    +            ..Self::from_weights(
    +                base_weight as u32,
    +                drain_weight as u32,
    +                TXIN_BASE_WEIGHT + drain_satisfaction_weight,
    +            )
    +        }
    +    }
    +
    +    pub fn long_term_feerate(&self) -> f32 {
    +        self.long_term_feerate.unwrap_or(self.target_feerate)
    +    }
    +
    +    pub fn drain_waste(&self) -> i64 {
    +        (self.drain_weight as f32 * self.target_feerate
    +            + self.spend_drain_weight as f32 * self.long_term_feerate()) as i64
    +    }
    +}
    +
    +/// [`CoinSelector`] is responsible for selecting and deselecting from a set of canididates.
    +#[derive(Debug, Clone)]
    +pub struct CoinSelector<'a> {
    +    pub opts: &'a CoinSelectorOpt,
    +    pub candidates: &'a Vec<WeightedValue>,
    +    selected: BTreeSet<usize>,
    +}
    +
    +impl<'a> CoinSelector<'a> {
    +    pub fn candidate(&self, index: usize) -> &WeightedValue {
    +        &self.candidates[index]
    +    }
    +
    +    pub fn new(candidates: &'a Vec<WeightedValue>, opts: &'a CoinSelectorOpt) -> Self {
    +        Self {
    +            candidates,
    +            selected: Default::default(),
    +            opts,
    +        }
    +    }
    +
    +    pub fn select(&mut self, index: usize) -> bool {
    +        assert!(index < self.candidates.len());
    +        self.selected.insert(index)
    +    }
    +
    +    pub fn deselect(&mut self, index: usize) -> bool {
    +        self.selected.remove(&index)
    +    }
    +
    +    pub fn is_selected(&self, index: usize) -> bool {
    +        self.selected.contains(&index)
    +    }
    +
    +    pub fn is_empty(&self) -> bool {
    +        self.selected.is_empty()
    +    }
    +
    +    /// Weight sum of all selected inputs.
    +    pub fn selected_weight(&self) -> u32 {
    +        self.selected
    +            .iter()
    +            .map(|&index| self.candidates[index].weight)
    +            .sum()
    +    }
    +
    +    /// Effective value sum of all selected inputs.
    +    pub fn selected_effective_value(&self) -> i64 {
    +        self.selected
    +            .iter()
    +            .map(|&index| self.candidates[index].effective_value(self.opts.target_feerate))
    +            .sum()
    +    }
    +
    +    /// Absolute value sum of all selected inputs.
    +    pub fn selected_absolute_value(&self) -> u64 {
    +        self.selected
    +            .iter()
    +            .map(|&index| self.candidates[index].value)
    +            .sum()
    +    }
    +
    +    /// Waste sum of all selected inputs.
    +    pub fn selected_waste(&self) -> i64 {
    +        (self.selected_weight() as f32 * (self.opts.target_feerate - self.opts.long_term_feerate()))
    +            as i64
    +    }
    +
    +    /// Current weight of template tx + selected inputs.
    +    pub fn current_weight(&self) -> u32 {
    +        let witness_header_extra_weight = self
    +            .selected()
    +            .find(|(_, wv)| wv.is_segwit)
    +            .map(|_| 2)
    +            .unwrap_or(0);
    +        let vin_count_varint_extra_weight = {
    +            let input_count = self.selected().map(|(_, wv)| wv.input_count).sum::<usize>();
    +            (varint_size(input_count) - 1) * 4
    +        };
    +        self.opts.base_weight
    +            + self.selected_weight()
    +            + witness_header_extra_weight
    +            + vin_count_varint_extra_weight
    +    }
    +
    +    /// Current excess.
    +    pub fn current_excess(&self) -> i64 {
    +        self.selected_effective_value() - self.effective_target()
    +    }
    +
    +    /// This is the effective target value.
    +    pub fn effective_target(&self) -> i64 {
    +        let (has_segwit, max_input_count) = self
    +            .candidates
    +            .iter()
    +            .fold((false, 0_usize), |(is_segwit, input_count), c| {
    +                (is_segwit || c.is_segwit, input_count + c.input_count)
    +            });
    +
    +        let effective_base_weight = self.opts.base_weight
    +            + if has_segwit { 2_u32 } else { 0_u32 }
    +            + (varint_size(max_input_count) - 1) * 4;
    +
    +        self.opts.target_value.unwrap_or(0) as i64
    +            + (effective_base_weight as f32 * self.opts.target_feerate).ceil() as i64
    +    }
    +
    +    pub fn selected_count(&self) -> usize {
    +        self.selected.len()
    +    }
    +
    +    pub fn selected(&self) -> impl Iterator<Item = (usize, &'a WeightedValue)> + '_ {
    +        self.selected
    +            .iter()
    +            .map(move |&index| (index, &self.candidates[index]))
    +    }
    +
    +    pub fn unselected(&self) -> impl Iterator<Item = (usize, &'a WeightedValue)> + '_ {
    +        self.candidates
    +            .iter()
    +            .enumerate()
    +            .filter(move |(index, _)| !self.selected.contains(index))
    +    }
    +
    +    pub fn selected_indexes(&self) -> impl Iterator<Item = usize> + '_ {
    +        self.selected.iter().cloned()
    +    }
    +
    +    pub fn unselected_indexes(&self) -> impl Iterator<Item = usize> + '_ {
    +        (0..self.candidates.len()).filter(move |index| !self.selected.contains(index))
    +    }
    +
    +    pub fn all_selected(&self) -> bool {
    +        self.selected.len() == self.candidates.len()
    +    }
    +
    +    pub fn select_all(&mut self) {
    +        self.selected = (0..self.candidates.len()).collect();
    +    }
    +
    +    pub fn select_until_finished(&mut self) -> Result<Selection, SelectionError> {
    +        let mut selection = self.finish();
    +
    +        if selection.is_ok() {
    +            return selection;
    +        }
    +
    +        let unselected = self.unselected_indexes().collect::<Vec<_>>();
    +
    +        for index in unselected {
    +            self.select(index);
    +            selection = self.finish();
    +
    +            if selection.is_ok() {
    +                break;
    +            }
    +        }
    +
    +        selection
    +    }
    +
    +    pub fn finish(&self) -> Result<Selection, SelectionError> {
    +        let weight_without_drain = self.current_weight();
    +        let weight_with_drain = weight_without_drain + self.opts.drain_weight;
    +
    +        let fee_without_drain =
    +            (weight_without_drain as f32 * self.opts.target_feerate).ceil() as u64;
    +        let fee_with_drain = (weight_with_drain as f32 * self.opts.target_feerate).ceil() as u64;
    +
    +        let inputs_minus_outputs = {
    +            let target_value = self.opts.target_value.unwrap_or(0);
    +            let selected = self.selected_absolute_value();
    +
    +            // find the largest unsatisfied constraint (if any), and return error of that constraint
    +            // "selected" should always be greater than or equal to these selected values
    +            [
    +                (
    +                    SelectionConstraint::TargetValue,
    +                    target_value.saturating_sub(selected),
    +                ),
    +                (
    +                    SelectionConstraint::TargetFee,
    +                    (target_value + fee_without_drain).saturating_sub(selected),
    +                ),
    +                (
    +                    SelectionConstraint::MinAbsoluteFee,
    +                    (target_value + self.opts.min_absolute_fee).saturating_sub(selected),
    +                ),
    +                (
    +                    SelectionConstraint::MinDrainValue,
    +                    // when we have no target value (hence no recipient txouts), we need to ensure
    +                    // the selected amount can satisfy requirements for a drain output (so we at
    +                    // least have one txout)
    +                    if self.opts.target_value.is_none() {
    +                        (fee_with_drain + self.opts.min_drain_value).saturating_sub(selected)
    +                    } else {
    +                        0
    +                    },
    +                ),
    +            ]
    +            .iter()
    +            .filter(|&(_, v)| v > &0)
    +            .max_by_key(|&(_, v)| v)
    +            .map_or(Ok(()), |(constraint, missing)| {
    +                Err(SelectionError {
    +                    selected,
    +                    missing: *missing,
    +                    constraint: *constraint,
    +                })
    +            })?;
    +
    +            selected - target_value
    +        };
    +
    +        let fee_without_drain = fee_without_drain.max(self.opts.min_absolute_fee);
    +        let fee_with_drain = fee_with_drain.max(self.opts.min_absolute_fee);
    +
    +        let excess_without_drain = inputs_minus_outputs - fee_without_drain;
    +        let input_waste = self.selected_waste();
    +
    +        // begin preparing excess strategies for final selection
    +        let mut excess_strategies = HashMap::new();
    +
    +        // only allow `ToFee` and `ToRecipient` excess strategies when we have a `target_value`,
    +        // otherwise we will result in a result with no txouts, or attempt to add value to an output
    +        // that does not exist
    +        if self.opts.target_value.is_some() {
    +            // no drain, excess to fee
    +            excess_strategies.insert(
    +                ExcessStrategyKind::ToFee,
    +                ExcessStrategy {
    +                    recipient_value: self.opts.target_value,
    +                    drain_value: None,
    +                    fee: fee_without_drain + excess_without_drain,
    +                    weight: weight_without_drain,
    +                    waste: input_waste + excess_without_drain as i64,
    +                },
    +            );
    +
    +            // no drain, excess to recipient
    +            // if `excess == 0`, this result will be the same as the previous, so don't consider it
    +            // if `max_extra_target == 0`, there is no leeway for this strategy
    +            if excess_without_drain > 0 && self.opts.max_extra_target > 0 {
    +                let extra_recipient_value =
    +                    core::cmp::min(self.opts.max_extra_target, excess_without_drain);
    +                let extra_fee = excess_without_drain - extra_recipient_value;
    +                excess_strategies.insert(
    +                    ExcessStrategyKind::ToRecipient,
    +                    ExcessStrategy {
    +                        recipient_value: self.opts.target_value.map(|v| v + extra_recipient_value),
    +                        drain_value: None,
    +                        fee: fee_without_drain + extra_fee,
    +                        weight: weight_without_drain,
    +                        waste: input_waste + extra_fee as i64,
    +                    },
    +                );
    +            }
    +        }
    +
    +        // with drain
    +        if fee_with_drain >= self.opts.min_absolute_fee
    +            && inputs_minus_outputs >= fee_with_drain + self.opts.min_drain_value
    +        {
    +            excess_strategies.insert(
    +                ExcessStrategyKind::ToDrain,
    +                ExcessStrategy {
    +                    recipient_value: self.opts.target_value,
    +                    drain_value: Some(inputs_minus_outputs.saturating_sub(fee_with_drain)),
    +                    fee: fee_with_drain,
    +                    weight: weight_with_drain,
    +                    waste: input_waste + self.opts.drain_waste(),
    +                },
    +            );
    +        }
    +
    +        debug_assert!(
    +            !excess_strategies.is_empty(),
    +            "should have at least one excess strategy"
    +        );
    +
    +        Ok(Selection {
    +            selected: self.selected.clone(),
    +            excess: excess_without_drain,
    +            excess_strategies,
    +        })
    +    }
    +}
    +
    +#[derive(Clone, Debug)]
    +pub struct SelectionError {
    +    selected: u64,
    +    missing: u64,
    +    constraint: SelectionConstraint,
    +}
    +
    +impl core::fmt::Display for SelectionError {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        let SelectionError {
    +            selected,
    +            missing,
    +            constraint,
    +        } = self;
    +        write!(
    +            f,
    +            "insufficient coins selected; selected={}, missing={}, unsatisfied_constraint={:?}",
    +            selected, missing, constraint
    +        )
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl std::error::Error for SelectionError {}
    +
    +#[derive(Clone, Copy, Debug, PartialEq, Eq)]
    +pub enum SelectionConstraint {
    +    /// The target is not met
    +    TargetValue,
    +    /// The target fee (given the feerate) is not met
    +    TargetFee,
    +    /// Min absolute fee is not met
    +    MinAbsoluteFee,
    +    /// Min drain value is not met
    +    MinDrainValue,
    +}
    +
    +impl core::fmt::Display for SelectionConstraint {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            SelectionConstraint::TargetValue => core::write!(f, "target_value"),
    +            SelectionConstraint::TargetFee => core::write!(f, "target_fee"),
    +            SelectionConstraint::MinAbsoluteFee => core::write!(f, "min_absolute_fee"),
    +            SelectionConstraint::MinDrainValue => core::write!(f, "min_drain_value"),
    +        }
    +    }
    +}
    +
    +#[derive(Clone, Debug)]
    +pub struct Selection {
    +    pub selected: BTreeSet<usize>,
    +    pub excess: u64,
    +    pub excess_strategies: HashMap<ExcessStrategyKind, ExcessStrategy>,
    +}
    +
    +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, core::hash::Hash)]
    +pub enum ExcessStrategyKind {
    +    ToFee,
    +    ToRecipient,
    +    ToDrain,
    +}
    +
    +#[derive(Clone, Copy, Debug)]
    +pub struct ExcessStrategy {
    +    pub recipient_value: Option<u64>,
    +    pub drain_value: Option<u64>,
    +    pub fee: u64,
    +    pub weight: u32,
    +    pub waste: i64,
    +}
    +
    +impl Selection {
    +    pub fn apply_selection<'a, T>(
    +        &'a self,
    +        candidates: &'a [T],
    +    ) -> impl Iterator<Item = &'a T> + 'a {
    +        self.selected.iter().map(move |i| &candidates[*i])
    +    }
    +
    +    /// Returns the [`ExcessStrategy`] that results in the least waste.
    +    pub fn best_strategy(&self) -> (&ExcessStrategyKind, &ExcessStrategy) {
    +        self.excess_strategies
    +            .iter()
    +            .min_by_key(|&(_, a)| a.waste)
    +            .expect("selection has no excess strategy")
    +    }
    +}
    +
    +impl core::fmt::Display for ExcessStrategyKind {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            ExcessStrategyKind::ToFee => core::write!(f, "to_fee"),
    +            ExcessStrategyKind::ToRecipient => core::write!(f, "to_recipient"),
    +            ExcessStrategyKind::ToDrain => core::write!(f, "to_drain"),
    +        }
    +    }
    +}
    +
    +impl ExcessStrategy {
    +    /// Returns feerate in sats/wu.
    +    pub fn feerate(&self) -> f32 {
    +        self.fee as f32 / self.weight as f32
    +    }
    +}
    +
    +#[cfg(test)]
    +mod test {
    +    use crate::{ExcessStrategyKind, SelectionConstraint};
    +
    +    use super::{CoinSelector, CoinSelectorOpt, WeightedValue};
    +
    +    /// Ensure `target_value` is respected. Can't have no disrespect.
    +    #[test]
    +    fn target_value_respected() {
    +        let target_value = 1000_u64;
    +
    +        let candidates = (500..1500_u64)
    +            .map(|value| WeightedValue {
    +                value,
    +                weight: 100,
    +                input_count: 1,
    +                is_segwit: false,
    +            })
    +            .collect::<super::Vec<_>>();
    +
    +        let opts = CoinSelectorOpt {
    +            target_value: Some(target_value),
    +            max_extra_target: 0,
    +            target_feerate: 0.00,
    +            long_term_feerate: None,
    +            min_absolute_fee: 0,
    +            base_weight: 10,
    +            drain_weight: 10,
    +            spend_drain_weight: 10,
    +            min_drain_value: 10,
    +        };
    +
    +        for (index, v) in candidates.iter().enumerate() {
    +            let mut selector = CoinSelector::new(&candidates, &opts);
    +            assert!(selector.select(index));
    +
    +            let res = selector.finish();
    +            if v.value < opts.target_value.unwrap_or(0) {
    +                let err = res.expect_err("should have failed");
    +                assert_eq!(err.selected, v.value);
    +                assert_eq!(err.missing, target_value - v.value);
    +                assert_eq!(err.constraint, SelectionConstraint::MinAbsoluteFee);
    +            } else {
    +                let sel = res.expect("should have succeeded");
    +                assert_eq!(sel.excess, v.value - opts.target_value.unwrap_or(0));
    +            }
    +        }
    +    }
    +
    +    #[test]
    +    fn drain_all() {
    +        let candidates = (0..100)
    +            .map(|_| WeightedValue {
    +                value: 666,
    +                weight: 166,
    +                input_count: 1,
    +                is_segwit: false,
    +            })
    +            .collect::<super::Vec<_>>();
    +
    +        let opts = CoinSelectorOpt {
    +            target_value: None,
    +            max_extra_target: 0,
    +            target_feerate: 0.25,
    +            long_term_feerate: None,
    +            min_absolute_fee: 0,
    +            base_weight: 10,
    +            drain_weight: 100,
    +            spend_drain_weight: 66,
    +            min_drain_value: 1000,
    +        };
    +
    +        let selection = CoinSelector::new(&candidates, &opts)
    +            .select_until_finished()
    +            .expect("should succeed");
    +
    +        assert!(selection.selected.len() > 1);
    +        assert_eq!(selection.excess_strategies.len(), 1);
    +
    +        let (kind, strategy) = selection.best_strategy();
    +        assert_eq!(*kind, ExcessStrategyKind::ToDrain);
    +        assert!(strategy.recipient_value.is_none());
    +        assert!(strategy.drain_value.is_some());
    +    }
    +
    +    /// TODO: Tests to add:
    +    /// * `finish` should ensure at least `target_value` is selected.
    +    /// * actual feerate should be equal or higher than `target_feerate`.
    +    /// * actual drain value should be equal or higher than `min_drain_value` (or else no drain).
    +    fn _todo() {}
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/lib.rs.html new file mode 100644 index 0000000000..9e5ff002d3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_coin_select/lib.rs.html @@ -0,0 +1,68 @@ +lib.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +
    #![no_std]
    +
    +#[cfg(feature = "std")]
    +extern crate std;
    +
    +#[macro_use]
    +extern crate alloc;
    +extern crate bdk_chain;
    +
    +use alloc::vec::Vec;
    +use bdk_chain::{
    +    bitcoin,
    +    collections::{BTreeSet, HashMap},
    +};
    +use bitcoin::{LockTime, Transaction, TxOut};
    +use core::fmt::{Debug, Display};
    +
    +mod coin_selector;
    +pub use coin_selector::*;
    +
    +mod bnb;
    +pub use bnb::*;
    +
    +/// Txin "base" fields include `outpoint` (32+4) and `nSequence` (4). This does not include
    +/// `scriptSigLen` or `scriptSig`.
    +pub const TXIN_BASE_WEIGHT: u32 = (32 + 4 + 4) * 4;
    +
    +/// Helper to calculate varint size. `v` is the value the varint represents.
    +// Shamelessly copied from
    +// https://github.com/rust-bitcoin/rust-miniscript/blob/d5615acda1a7fdc4041a11c1736af139b8c7ebe8/src/util.rs#L8
    +pub(crate) fn varint_size(v: usize) -> u32 {
    +    bitcoin::VarInt(v as u64).len() as u32
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_electrum/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_electrum/lib.rs.html new file mode 100644 index 0000000000..d70e71136b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_electrum/lib.rs.html @@ -0,0 +1,1178 @@ +lib.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +
    //! This crate is used for updating structures of the [`bdk_chain`] crate with data from electrum.
    +//!
    +//! The star of the show is the [`ElectrumExt::scan`] method, which scans for relevant blockchain
    +//! data (via electrum) and outputs an [`ElectrumUpdate`].
    +//!
    +//! An [`ElectrumUpdate`] only includes `txid`s and no full transactions. The caller is responsible
    +//! for obtaining full transactions before applying. This can be done with
    +//! these steps:
    +//!
    +//! 1. Determine which full transactions are missing. The method [`missing_full_txs`] of
    +//! [`ElectrumUpdate`] can be used.
    +//!
    +//! 2. Obtaining the full transactions. To do this via electrum, the method
    +//! [`batch_transaction_get`] can be used.
    +//!
    +//! Refer to [`bdk_electrum_example`] for a complete example.
    +//!
    +//! [`ElectrumClient::scan`]: ElectrumClient::scan
    +//! [`missing_full_txs`]: ElectrumUpdate::missing_full_txs
    +//! [`batch_transaction_get`]: ElectrumApi::batch_transaction_get
    +//! [`bdk_electrum_example`]: https://github.com/LLFourn/bdk_core_staging/tree/master/bdk_electrum_example
    +
    +use std::{
    +    collections::{BTreeMap, HashMap},
    +    fmt::Debug,
    +};
    +
    +pub use bdk_chain;
    +use bdk_chain::{
    +    bitcoin::{hashes::hex::FromHex, BlockHash, OutPoint, Script, Transaction, Txid},
    +    chain_graph::{self, ChainGraph},
    +    keychain::KeychainScan,
    +    sparse_chain::{self, ChainPosition, SparseChain},
    +    tx_graph::TxGraph,
    +    BlockId, ConfirmationTime, TxHeight,
    +};
    +pub use electrum_client;
    +use electrum_client::{Client, ElectrumApi, Error};
    +
    +/// Trait to extend [`electrum_client::Client`] functionality.
    +///
    +/// Refer to [crate-level documentation] for more.
    +///
    +/// [crate-level documentation]: crate
    +pub trait ElectrumExt {
    +    /// Fetch the latest block height.
    +    fn get_tip(&self) -> Result<(u32, BlockHash), Error>;
    +
    +    /// Scan the blockchain (via electrum) for the data specified. This returns a [`ElectrumUpdate`]
    +    /// which can be transformed into a [`KeychainScan`] after we find all the missing full
    +    /// transactions.
    +    ///
    +    /// - `local_chain`: the most recent block hashes present locally
    +    /// - `keychain_spks`: keychains that we want to scan transactions for
    +    /// - `txids`: transactions that we want updated [`ChainPosition`]s for
    +    /// - `outpoints`: transactions associated with these outpoints (residing, spending) that we
    +    ///     want to included in the update
    +    fn scan<K: Ord + Clone>(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, Script)>>,
    +        txids: impl IntoIterator<Item = Txid>,
    +        outpoints: impl IntoIterator<Item = OutPoint>,
    +        stop_gap: usize,
    +        batch_size: usize,
    +    ) -> Result<ElectrumUpdate<K, TxHeight>, Error>;
    +
    +    /// Convenience method to call [`scan`] without requiring a keychain.
    +    ///
    +    /// [`scan`]: ElectrumExt::scan
    +    fn scan_without_keychain(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        misc_spks: impl IntoIterator<Item = Script>,
    +        txids: impl IntoIterator<Item = Txid>,
    +        outpoints: impl IntoIterator<Item = OutPoint>,
    +        batch_size: usize,
    +    ) -> Result<SparseChain, Error> {
    +        let spk_iter = misc_spks
    +            .into_iter()
    +            .enumerate()
    +            .map(|(i, spk)| (i as u32, spk));
    +
    +        self.scan(
    +            local_chain,
    +            [((), spk_iter)].into(),
    +            txids,
    +            outpoints,
    +            usize::MAX,
    +            batch_size,
    +        )
    +        .map(|u| u.chain_update)
    +    }
    +}
    +
    +impl ElectrumExt for Client {
    +    fn get_tip(&self) -> Result<(u32, BlockHash), Error> {
    +        // TODO: unsubscribe when added to the client, or is there a better call to use here?
    +        self.block_headers_subscribe()
    +            .map(|data| (data.height as u32, data.header.block_hash()))
    +    }
    +
    +    fn scan<K: Ord + Clone>(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, Script)>>,
    +        txids: impl IntoIterator<Item = Txid>,
    +        outpoints: impl IntoIterator<Item = OutPoint>,
    +        stop_gap: usize,
    +        batch_size: usize,
    +    ) -> Result<ElectrumUpdate<K, TxHeight>, Error> {
    +        let mut request_spks = keychain_spks
    +            .into_iter()
    +            .map(|(k, s)| {
    +                let iter = s.into_iter();
    +                (k, iter)
    +            })
    +            .collect::<BTreeMap<K, _>>();
    +        let mut scanned_spks = BTreeMap::<(K, u32), (Script, bool)>::new();
    +
    +        let txids = txids.into_iter().collect::<Vec<_>>();
    +        let outpoints = outpoints.into_iter().collect::<Vec<_>>();
    +
    +        let update = loop {
    +            let mut update = prepare_update(self, local_chain)?;
    +
    +            if !request_spks.is_empty() {
    +                if !scanned_spks.is_empty() {
    +                    let mut scanned_spk_iter = scanned_spks
    +                        .iter()
    +                        .map(|(i, (spk, _))| (i.clone(), spk.clone()));
    +                    match populate_with_spks::<K, _, _>(
    +                        self,
    +                        &mut update,
    +                        &mut scanned_spk_iter,
    +                        stop_gap,
    +                        batch_size,
    +                    ) {
    +                        Err(InternalError::Reorg) => continue,
    +                        Err(InternalError::ElectrumError(e)) => return Err(e),
    +                        Ok(mut spks) => scanned_spks.append(&mut spks),
    +                    };
    +                }
    +                for (keychain, keychain_spks) in &mut request_spks {
    +                    match populate_with_spks::<K, u32, _>(
    +                        self,
    +                        &mut update,
    +                        keychain_spks,
    +                        stop_gap,
    +                        batch_size,
    +                    ) {
    +                        Err(InternalError::Reorg) => continue,
    +                        Err(InternalError::ElectrumError(e)) => return Err(e),
    +                        Ok(spks) => scanned_spks.extend(
    +                            spks.into_iter()
    +                                .map(|(spk_i, spk)| ((keychain.clone(), spk_i), spk)),
    +                        ),
    +                    };
    +                }
    +            }
    +
    +            match populate_with_txids(self, &mut update, &mut txids.iter().cloned()) {
    +                Err(InternalError::Reorg) => continue,
    +                Err(InternalError::ElectrumError(e)) => return Err(e),
    +                Ok(_) => {}
    +            }
    +
    +            match populate_with_outpoints(self, &mut update, &mut outpoints.iter().cloned()) {
    +                Err(InternalError::Reorg) => continue,
    +                Err(InternalError::ElectrumError(e)) => return Err(e),
    +                Ok(_txs) => { /* [TODO] cache full txs to reduce bandwidth */ }
    +            }
    +
    +            // check for reorgs during scan process
    +            let our_tip = update
    +                .latest_checkpoint()
    +                .expect("update must have atleast one checkpoint");
    +            let server_blockhash = self.block_header(our_tip.height as usize)?.block_hash();
    +            if our_tip.hash != server_blockhash {
    +                continue; // reorg
    +            } else {
    +                break update;
    +            }
    +        };
    +
    +        let last_active_index = request_spks
    +            .into_keys()
    +            .filter_map(|k| {
    +                scanned_spks
    +                    .range((k.clone(), u32::MIN)..=(k.clone(), u32::MAX))
    +                    .rev()
    +                    .find(|(_, (_, active))| *active)
    +                    .map(|((_, i), _)| (k, *i))
    +            })
    +            .collect::<BTreeMap<_, _>>();
    +
    +        Ok(ElectrumUpdate {
    +            chain_update: update,
    +            last_active_indices: last_active_index,
    +        })
    +    }
    +}
    +
    +/// The result of [`ElectrumExt::scan`].
    +pub struct ElectrumUpdate<K, P> {
    +    /// The internal [`SparseChain`] update.
    +    pub chain_update: SparseChain<P>,
    +    /// The last keychain script pubkey indices which had transaction histories.
    +    pub last_active_indices: BTreeMap<K, u32>,
    +}
    +
    +impl<K, P> Default for ElectrumUpdate<K, P> {
    +    fn default() -> Self {
    +        Self {
    +            chain_update: Default::default(),
    +            last_active_indices: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<K, P> AsRef<SparseChain<P>> for ElectrumUpdate<K, P> {
    +    fn as_ref(&self) -> &SparseChain<P> {
    +        &self.chain_update
    +    }
    +}
    +
    +impl<K: Ord + Clone + Debug, P: ChainPosition> ElectrumUpdate<K, P> {
    +    /// Return a list of missing full transactions that are required to [`inflate_update`].
    +    ///
    +    /// [`inflate_update`]: bdk_chain::chain_graph::ChainGraph::inflate_update
    +    pub fn missing_full_txs<G>(&self, graph: G) -> Vec<&Txid>
    +    where
    +        G: AsRef<TxGraph>,
    +    {
    +        self.chain_update
    +            .txids()
    +            .filter(|(_, txid)| graph.as_ref().get_tx(*txid).is_none())
    +            .map(|(_, txid)| txid)
    +            .collect()
    +    }
    +
    +    /// Transform the [`ElectrumUpdate`] into a [`KeychainScan`] which can be applied to a
    +    /// `tracker`.
    +    ///
    +    /// This will fail if there are missing full transactions not provided via `new_txs`.
    +    pub fn into_keychain_scan<CG>(
    +        self,
    +        new_txs: Vec<Transaction>,
    +        chain_graph: &CG,
    +    ) -> Result<KeychainScan<K, P>, chain_graph::NewError<P>>
    +    where
    +        CG: AsRef<ChainGraph<P>>,
    +    {
    +        Ok(KeychainScan {
    +            update: chain_graph
    +                .as_ref()
    +                .inflate_update(self.chain_update, new_txs)?,
    +            last_active_indices: self.last_active_indices,
    +        })
    +    }
    +}
    +
    +impl<K: Ord + Clone + Debug> ElectrumUpdate<K, TxHeight> {
    +    /// Creates [`ElectrumUpdate<K, ConfirmationTime>`] from [`ElectrumUpdate<K, TxHeight>`].
    +    pub fn into_confirmation_time_update(
    +        self,
    +        client: &electrum_client::Client,
    +    ) -> Result<ElectrumUpdate<K, ConfirmationTime>, Error> {
    +        let heights = self
    +            .chain_update
    +            .range_txids_by_height(..TxHeight::Unconfirmed)
    +            .map(|(h, _)| match h {
    +                TxHeight::Confirmed(h) => *h,
    +                _ => unreachable!("already filtered out unconfirmed"),
    +            })
    +            .collect::<Vec<u32>>();
    +
    +        let height_to_time = heights
    +            .clone()
    +            .into_iter()
    +            .zip(
    +                client
    +                    .batch_block_header(heights)?
    +                    .into_iter()
    +                    .map(|bh| bh.time as u64),
    +            )
    +            .collect::<HashMap<u32, u64>>();
    +
    +        let mut new_update = SparseChain::<ConfirmationTime>::from_checkpoints(
    +            self.chain_update.range_checkpoints(..),
    +        );
    +
    +        for &(tx_height, txid) in self.chain_update.txids() {
    +            let conf_time = match tx_height {
    +                TxHeight::Confirmed(height) => ConfirmationTime::Confirmed {
    +                    height,
    +                    time: height_to_time[&height],
    +                },
    +                TxHeight::Unconfirmed => ConfirmationTime::Unconfirmed,
    +            };
    +            let _ = new_update.insert_tx(txid, conf_time).expect("must insert");
    +        }
    +
    +        Ok(ElectrumUpdate {
    +            chain_update: new_update,
    +            last_active_indices: self.last_active_indices,
    +        })
    +    }
    +}
    +
    +#[derive(Debug)]
    +enum InternalError {
    +    ElectrumError(Error),
    +    Reorg,
    +}
    +
    +impl From<electrum_client::Error> for InternalError {
    +    fn from(value: electrum_client::Error) -> Self {
    +        Self::ElectrumError(value)
    +    }
    +}
    +
    +fn get_tip(client: &Client) -> Result<(u32, BlockHash), Error> {
    +    // TODO: unsubscribe when added to the client, or is there a better call to use here?
    +    client
    +        .block_headers_subscribe()
    +        .map(|data| (data.height as u32, data.header.block_hash()))
    +}
    +
    +/// Prepare an update sparsechain "template" based on the checkpoints of the `local_chain`.
    +fn prepare_update(
    +    client: &Client,
    +    local_chain: &BTreeMap<u32, BlockHash>,
    +) -> Result<SparseChain, Error> {
    +    let mut update = SparseChain::default();
    +
    +    // Find local chain block that is still there so our update can connect to the local chain.
    +    for (&existing_height, &existing_hash) in local_chain.iter().rev() {
    +        // TODO: a batch request may be safer, as a reorg that happens when we are obtaining
    +        //       `block_header`s will result in inconsistencies
    +        let current_hash = client.block_header(existing_height as usize)?.block_hash();
    +        let _ = update
    +            .insert_checkpoint(BlockId {
    +                height: existing_height,
    +                hash: current_hash,
    +            })
    +            .expect("This never errors because we are working with a fresh chain");
    +
    +        if current_hash == existing_hash {
    +            break;
    +        }
    +    }
    +
    +    // Insert the new tip so new transactions will be accepted into the sparse chain.
    +    let tip = {
    +        let (height, hash) = get_tip(client)?;
    +        BlockId { height, hash }
    +    };
    +    if let Err(failure) = update.insert_checkpoint(tip) {
    +        match failure {
    +            sparse_chain::InsertCheckpointError::HashNotMatching { .. } => {
    +                // There has been a re-org before we even begin scanning addresses.
    +                // Just recursively call (this should never happen).
    +                return prepare_update(client, local_chain);
    +            }
    +        }
    +    }
    +
    +    Ok(update)
    +}
    +
    +/// This atrocity is required because electrum thinks height of 0 means "unconfirmed", but there is
    +/// such thing as a genesis block.
    +///
    +/// We contain an expection for the genesis coinbase txid to always have a chain position of
    +/// [`TxHeight::Confirmed(0)`].
    +fn determine_tx_height(raw_height: i32, tip_height: u32, txid: Txid) -> TxHeight {
    +    if txid
    +        == Txid::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")
    +            .expect("must deserialize genesis coinbase txid")
    +    {
    +        return TxHeight::Confirmed(0);
    +    }
    +    match raw_height {
    +        h if h <= 0 => {
    +            debug_assert!(
    +                h == 0 || h == -1,
    +                "unexpected height ({}) from electrum server",
    +                h
    +            );
    +            TxHeight::Unconfirmed
    +        }
    +        h => {
    +            let h = h as u32;
    +            if h > tip_height {
    +                TxHeight::Unconfirmed
    +            } else {
    +                TxHeight::Confirmed(h)
    +            }
    +        }
    +    }
    +}
    +
    +/// Populates the update [`SparseChain`] with related transactions and associated [`ChainPosition`]s
    +/// of the provided `outpoints` (this is the tx which contains the outpoint and the one spending the
    +/// outpoint).
    +///
    +/// Unfortunately this is awkward to implement as electrum does not provide such an API. Instead, we
    +/// will get the tx history of the outpoint's spk, and try to find the containing tx and the
    +/// spending tx.
    +fn populate_with_outpoints(
    +    client: &Client,
    +    update: &mut SparseChain,
    +    outpoints: &mut impl Iterator<Item = OutPoint>,
    +) -> Result<HashMap<Txid, Transaction>, InternalError> {
    +    let tip = update
    +        .latest_checkpoint()
    +        .expect("update must atleast have one checkpoint");
    +
    +    let mut full_txs = HashMap::new();
    +    for outpoint in outpoints {
    +        let txid = outpoint.txid;
    +        let tx = client.transaction_get(&txid)?;
    +        debug_assert_eq!(tx.txid(), txid);
    +        let txout = match tx.output.get(outpoint.vout as usize) {
    +            Some(txout) => txout,
    +            None => continue,
    +        };
    +
    +        // attempt to find the following transactions (alongside their chain positions), and
    +        // add to our sparsechain `update`:
    +        let mut has_residing = false; // tx in which the outpoint resides
    +        let mut has_spending = false; // tx that spends the outpoint
    +        for res in client.script_get_history(&txout.script_pubkey)? {
    +            if has_residing && has_spending {
    +                break;
    +            }
    +
    +            if res.tx_hash == txid {
    +                if has_residing {
    +                    continue;
    +                }
    +                has_residing = true;
    +                full_txs.insert(res.tx_hash, tx.clone());
    +            } else {
    +                if has_spending {
    +                    continue;
    +                }
    +                let res_tx = match full_txs.get(&res.tx_hash) {
    +                    Some(tx) => tx,
    +                    None => {
    +                        let res_tx = client.transaction_get(&res.tx_hash)?;
    +                        full_txs.insert(res.tx_hash, res_tx);
    +                        full_txs.get(&res.tx_hash).expect("just inserted")
    +                    }
    +                };
    +                has_spending = res_tx
    +                    .input
    +                    .iter()
    +                    .any(|txin| txin.previous_output == outpoint);
    +                if !has_spending {
    +                    continue;
    +                }
    +            };
    +
    +            let tx_height = determine_tx_height(res.height, tip.height, res.tx_hash);
    +
    +            if let Err(failure) = update.insert_tx(res.tx_hash, tx_height) {
    +                match failure {
    +                    sparse_chain::InsertTxError::TxTooHigh { .. } => {
    +                        unreachable!("we should never encounter this as we ensured height <= tip");
    +                    }
    +                    sparse_chain::InsertTxError::TxMovedUnexpectedly { .. } => {
    +                        return Err(InternalError::Reorg);
    +                    }
    +                }
    +            }
    +        }
    +    }
    +    Ok(full_txs)
    +}
    +
    +/// Populate an update [`SparseChain`] with transactions (and associated block positions) from
    +/// the given `txids`.
    +fn populate_with_txids(
    +    client: &Client,
    +    update: &mut SparseChain,
    +    txids: &mut impl Iterator<Item = Txid>,
    +) -> Result<(), InternalError> {
    +    let tip = update
    +        .latest_checkpoint()
    +        .expect("update must have atleast one checkpoint");
    +    for txid in txids {
    +        let tx = match client.transaction_get(&txid) {
    +            Ok(tx) => tx,
    +            Err(electrum_client::Error::Protocol(_)) => continue,
    +            Err(other_err) => return Err(other_err.into()),
    +        };
    +
    +        let spk = tx
    +            .output
    +            .get(0)
    +            .map(|txo| &txo.script_pubkey)
    +            .expect("tx must have an output");
    +
    +        let tx_height = match client
    +            .script_get_history(spk)?
    +            .into_iter()
    +            .find(|r| r.tx_hash == txid)
    +        {
    +            Some(r) => determine_tx_height(r.height, tip.height, r.tx_hash),
    +            None => continue,
    +        };
    +
    +        if let Err(failure) = update.insert_tx(txid, tx_height) {
    +            match failure {
    +                sparse_chain::InsertTxError::TxTooHigh { .. } => {
    +                    unreachable!("we should never encounter this as we ensured height <= tip");
    +                }
    +                sparse_chain::InsertTxError::TxMovedUnexpectedly { .. } => {
    +                    return Err(InternalError::Reorg);
    +                }
    +            }
    +        }
    +    }
    +    Ok(())
    +}
    +
    +/// Populate an update [`SparseChain`] with transactions (and associated block positions) from
    +/// the transaction history of the provided `spks`.
    +fn populate_with_spks<K, I, S>(
    +    client: &Client,
    +    update: &mut SparseChain,
    +    spks: &mut S,
    +    stop_gap: usize,
    +    batch_size: usize,
    +) -> Result<BTreeMap<I, (Script, bool)>, InternalError>
    +where
    +    K: Ord + Clone,
    +    I: Ord + Clone,
    +    S: Iterator<Item = (I, Script)>,
    +{
    +    let tip = update.latest_checkpoint().map_or(0, |cp| cp.height);
    +    let mut unused_spk_count = 0_usize;
    +    let mut scanned_spks = BTreeMap::new();
    +
    +    loop {
    +        let spks = (0..batch_size)
    +            .map_while(|_| spks.next())
    +            .collect::<Vec<_>>();
    +        if spks.is_empty() {
    +            return Ok(scanned_spks);
    +        }
    +
    +        let spk_histories = client.batch_script_get_history(spks.iter().map(|(_, s)| s))?;
    +
    +        for ((spk_index, spk), spk_history) in spks.into_iter().zip(spk_histories) {
    +            if spk_history.is_empty() {
    +                scanned_spks.insert(spk_index, (spk, false));
    +                unused_spk_count += 1;
    +                if unused_spk_count > stop_gap {
    +                    return Ok(scanned_spks);
    +                }
    +                continue;
    +            } else {
    +                scanned_spks.insert(spk_index, (spk, true));
    +                unused_spk_count = 0;
    +            }
    +
    +            for tx in spk_history {
    +                let tx_height = determine_tx_height(tx.height, tip, tx.tx_hash);
    +
    +                if let Err(failure) = update.insert_tx(tx.tx_hash, tx_height) {
    +                    match failure {
    +                        sparse_chain::InsertTxError::TxTooHigh { .. } => {
    +                            unreachable!(
    +                                "we should never encounter this as we ensured height <= tip"
    +                            );
    +                        }
    +                        sparse_chain::InsertTxError::TxMovedUnexpectedly { .. } => {
    +                            return Err(InternalError::Reorg);
    +                        }
    +                    }
    +                }
    +            }
    +        }
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/async_ext.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/async_ext.rs.html new file mode 100644 index 0000000000..0907486e53 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/async_ext.rs.html @@ -0,0 +1,620 @@ +async_ext.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +
    use std::collections::BTreeMap;
    +
    +use async_trait::async_trait;
    +use bdk_chain::{
    +    bitcoin::{BlockHash, OutPoint, Script, Txid},
    +    chain_graph::ChainGraph,
    +    keychain::KeychainScan,
    +    sparse_chain, BlockId, ConfirmationTime,
    +};
    +use esplora_client::{Error, OutputStatus};
    +use futures::stream::{FuturesOrdered, TryStreamExt};
    +
    +use crate::map_confirmation_time;
    +
    +#[cfg(feature = "async")]
    +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
    +#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
    +pub trait EsploraAsyncExt {
    +    /// Scan the blockchain (via esplora) for the data specified and returns a [`KeychainScan`].
    +    ///
    +    /// - `local_chain`: the most recent block hashes present locally
    +    /// - `keychain_spks`: keychains that we want to scan transactions for
    +    /// - `txids`: transactions that we want updated [`ChainPosition`]s for
    +    /// - `outpoints`: transactions associated with these outpoints (residing, spending) that we
    +    ///     want to included in the update
    +    ///
    +    /// The scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated
    +    /// transactions. `parallel_requests` specifies the max number of HTTP requests to make in
    +    /// parallel.
    +    ///
    +    /// [`ChainPosition`]: bdk_chain::sparse_chain::ChainPosition
    +    #[allow(clippy::result_large_err)] // FIXME
    +    async fn scan<K: Ord + Clone + Send>(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        keychain_spks: BTreeMap<
    +            K,
    +            impl IntoIterator<IntoIter = impl Iterator<Item = (u32, Script)> + Send> + Send,
    +        >,
    +        txids: impl IntoIterator<IntoIter = impl Iterator<Item = Txid> + Send> + Send,
    +        outpoints: impl IntoIterator<IntoIter = impl Iterator<Item = OutPoint> + Send> + Send,
    +        stop_gap: usize,
    +        parallel_requests: usize,
    +    ) -> Result<KeychainScan<K, ConfirmationTime>, Error>;
    +
    +    /// Convenience method to call [`scan`] without requiring a keychain.
    +    ///
    +    /// [`scan`]: EsploraAsyncExt::scan
    +    #[allow(clippy::result_large_err)] // FIXME
    +    async fn scan_without_keychain(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        misc_spks: impl IntoIterator<IntoIter = impl Iterator<Item = Script> + Send> + Send,
    +        txids: impl IntoIterator<IntoIter = impl Iterator<Item = Txid> + Send> + Send,
    +        outpoints: impl IntoIterator<IntoIter = impl Iterator<Item = OutPoint> + Send> + Send,
    +        parallel_requests: usize,
    +    ) -> Result<ChainGraph<ConfirmationTime>, Error> {
    +        let wallet_scan = self
    +            .scan(
    +                local_chain,
    +                [(
    +                    (),
    +                    misc_spks
    +                        .into_iter()
    +                        .enumerate()
    +                        .map(|(i, spk)| (i as u32, spk)),
    +                )]
    +                .into(),
    +                txids,
    +                outpoints,
    +                usize::MAX,
    +                parallel_requests,
    +            )
    +            .await?;
    +
    +        Ok(wallet_scan.update)
    +    }
    +}
    +
    +#[cfg(feature = "async")]
    +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
    +#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
    +impl EsploraAsyncExt for esplora_client::AsyncClient {
    +    #[allow(clippy::result_large_err)] // FIXME
    +    async fn scan<K: Ord + Clone + Send>(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        keychain_spks: BTreeMap<
    +            K,
    +            impl IntoIterator<IntoIter = impl Iterator<Item = (u32, Script)> + Send> + Send,
    +        >,
    +        txids: impl IntoIterator<IntoIter = impl Iterator<Item = Txid> + Send> + Send,
    +        outpoints: impl IntoIterator<IntoIter = impl Iterator<Item = OutPoint> + Send> + Send,
    +        stop_gap: usize,
    +        parallel_requests: usize,
    +    ) -> Result<KeychainScan<K, ConfirmationTime>, Error> {
    +        let txids = txids.into_iter();
    +        let outpoints = outpoints.into_iter();
    +        let parallel_requests = parallel_requests.max(1);
    +        let mut scan = KeychainScan::default();
    +        let update = &mut scan.update;
    +        let last_active_indices = &mut scan.last_active_indices;
    +
    +        for (&height, &original_hash) in local_chain.iter().rev() {
    +            let update_block_id = BlockId {
    +                height,
    +                hash: self.get_block_hash(height).await?,
    +            };
    +            let _ = update
    +                .insert_checkpoint(update_block_id)
    +                .expect("cannot repeat height here");
    +            if update_block_id.hash == original_hash {
    +                break;
    +            }
    +        }
    +        let tip_at_start = BlockId {
    +            height: self.get_height().await?,
    +            hash: self.get_tip_hash().await?,
    +        };
    +        if let Err(failure) = update.insert_checkpoint(tip_at_start) {
    +            match failure {
    +                sparse_chain::InsertCheckpointError::HashNotMatching { .. } => {
    +                    // there has been a re-org before we started scanning. We haven't consumed any iterators so it's safe to recursively call.
    +                    return EsploraAsyncExt::scan(
    +                        self,
    +                        local_chain,
    +                        keychain_spks,
    +                        txids,
    +                        outpoints,
    +                        stop_gap,
    +                        parallel_requests,
    +                    )
    +                    .await;
    +                }
    +            }
    +        }
    +
    +        for (keychain, spks) in keychain_spks {
    +            let mut spks = spks.into_iter();
    +            let mut last_active_index = None;
    +            let mut empty_scripts = 0;
    +            type IndexWithTxs = (u32, Vec<esplora_client::Tx>);
    +
    +            loop {
    +                let futures: FuturesOrdered<_> = (0..parallel_requests)
    +                    .filter_map(|_| {
    +                        let (index, script) = spks.next()?;
    +                        let client = self.clone();
    +                        Some(async move {
    +                            let mut related_txs = client.scripthash_txs(&script, None).await?;
    +
    +                            let n_confirmed =
    +                                related_txs.iter().filter(|tx| tx.status.confirmed).count();
    +                            // esplora pages on 25 confirmed transactions. If there's 25 or more we
    +                            // keep requesting to see if there's more.
    +                            if n_confirmed >= 25 {
    +                                loop {
    +                                    let new_related_txs = client
    +                                        .scripthash_txs(
    +                                            &script,
    +                                            Some(related_txs.last().unwrap().txid),
    +                                        )
    +                                        .await?;
    +                                    let n = new_related_txs.len();
    +                                    related_txs.extend(new_related_txs);
    +                                    // we've reached the end
    +                                    if n < 25 {
    +                                        break;
    +                                    }
    +                                }
    +                            }
    +
    +                            Result::<_, esplora_client::Error>::Ok((index, related_txs))
    +                        })
    +                    })
    +                    .collect();
    +
    +                let n_futures = futures.len();
    +
    +                let idx_with_tx: Vec<IndexWithTxs> = futures.try_collect().await?;
    +
    +                for (index, related_txs) in idx_with_tx {
    +                    if related_txs.is_empty() {
    +                        empty_scripts += 1;
    +                    } else {
    +                        last_active_index = Some(index);
    +                        empty_scripts = 0;
    +                    }
    +                    for tx in related_txs {
    +                        let confirmation_time =
    +                            map_confirmation_time(&tx.status, tip_at_start.height);
    +
    +                        if let Err(failure) = update.insert_tx(tx.to_tx(), confirmation_time) {
    +                            use bdk_chain::{
    +                                chain_graph::InsertTxError, sparse_chain::InsertTxError::*,
    +                            };
    +                            match failure {
    +                                InsertTxError::Chain(TxTooHigh { .. }) => {
    +                                    unreachable!("chain position already checked earlier")
    +                                }
    +                                InsertTxError::Chain(TxMovedUnexpectedly { .. })
    +                                | InsertTxError::UnresolvableConflict(_) => {
    +                                    /* implies reorg during scan. We deal with that below */
    +                                }
    +                            }
    +                        }
    +                    }
    +                }
    +
    +                if n_futures == 0 || empty_scripts >= stop_gap {
    +                    break;
    +                }
    +            }
    +
    +            if let Some(last_active_index) = last_active_index {
    +                last_active_indices.insert(keychain, last_active_index);
    +            }
    +        }
    +
    +        for txid in txids {
    +            let (tx, tx_status) =
    +                match (self.get_tx(&txid).await?, self.get_tx_status(&txid).await?) {
    +                    (Some(tx), Some(tx_status)) => (tx, tx_status),
    +                    _ => continue,
    +                };
    +
    +            let confirmation_time = map_confirmation_time(&tx_status, tip_at_start.height);
    +
    +            if let Err(failure) = update.insert_tx(tx, confirmation_time) {
    +                use bdk_chain::{chain_graph::InsertTxError, sparse_chain::InsertTxError::*};
    +                match failure {
    +                    InsertTxError::Chain(TxTooHigh { .. }) => {
    +                        unreachable!("chain position already checked earlier")
    +                    }
    +                    InsertTxError::Chain(TxMovedUnexpectedly { .. })
    +                    | InsertTxError::UnresolvableConflict(_) => {
    +                        /* implies reorg during scan. We deal with that below */
    +                    }
    +                }
    +            }
    +        }
    +
    +        for op in outpoints {
    +            let mut op_txs = Vec::with_capacity(2);
    +            if let (Some(tx), Some(tx_status)) = (
    +                self.get_tx(&op.txid).await?,
    +                self.get_tx_status(&op.txid).await?,
    +            ) {
    +                op_txs.push((tx, tx_status));
    +                if let Some(OutputStatus {
    +                    txid: Some(txid),
    +                    status: Some(spend_status),
    +                    ..
    +                }) = self.get_output_status(&op.txid, op.vout as _).await?
    +                {
    +                    if let Some(spend_tx) = self.get_tx(&txid).await? {
    +                        op_txs.push((spend_tx, spend_status));
    +                    }
    +                }
    +            }
    +
    +            for (tx, status) in op_txs {
    +                let confirmation_time = map_confirmation_time(&status, tip_at_start.height);
    +
    +                if let Err(failure) = update.insert_tx(tx, confirmation_time) {
    +                    use bdk_chain::{chain_graph::InsertTxError, sparse_chain::InsertTxError::*};
    +                    match failure {
    +                        InsertTxError::Chain(TxTooHigh { .. }) => {
    +                            unreachable!("chain position already checked earlier")
    +                        }
    +                        InsertTxError::Chain(TxMovedUnexpectedly { .. })
    +                        | InsertTxError::UnresolvableConflict(_) => {
    +                            /* implies reorg during scan. We deal with that below */
    +                        }
    +                    }
    +                }
    +            }
    +        }
    +
    +        let reorg_occurred = {
    +            if let Some(checkpoint) = update.chain().latest_checkpoint() {
    +                self.get_block_hash(checkpoint.height).await? != checkpoint.hash
    +            } else {
    +                false
    +            }
    +        };
    +
    +        if reorg_occurred {
    +            // A reorg occurred so lets find out where all the txids we found are in the chain now.
    +            // XXX: collect required because of weird type naming issues
    +            let txids_found = update
    +                .chain()
    +                .txids()
    +                .map(|(_, txid)| *txid)
    +                .collect::<Vec<_>>();
    +            scan.update = EsploraAsyncExt::scan_without_keychain(
    +                self,
    +                local_chain,
    +                [],
    +                txids_found,
    +                [],
    +                parallel_requests,
    +            )
    +            .await?;
    +        }
    +
    +        Ok(scan)
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/blocking_ext.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/blocking_ext.rs.html new file mode 100644 index 0000000000..864634ddf2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/blocking_ext.rs.html @@ -0,0 +1,582 @@ +blocking_ext.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +
    use std::collections::BTreeMap;
    +
    +use bdk_chain::{
    +    bitcoin::{BlockHash, OutPoint, Script, Txid},
    +    chain_graph::ChainGraph,
    +    keychain::KeychainScan,
    +    sparse_chain, BlockId, ConfirmationTime,
    +};
    +use esplora_client::{Error, OutputStatus};
    +
    +use crate::map_confirmation_time;
    +
    +/// Trait to extend [`esplora_client::BlockingClient`] functionality.
    +///
    +/// Refer to [crate-level documentation] for more.
    +///
    +/// [crate-level documentation]: crate
    +pub trait EsploraExt {
    +    /// Scan the blockchain (via esplora) for the data specified and returns a [`KeychainScan`].
    +    ///
    +    /// - `local_chain`: the most recent block hashes present locally
    +    /// - `keychain_spks`: keychains that we want to scan transactions for
    +    /// - `txids`: transactions that we want updated [`ChainPosition`]s for
    +    /// - `outpoints`: transactions associated with these outpoints (residing, spending) that we
    +    ///     want to included in the update
    +    ///
    +    /// The scan for each keychain stops after a gap of `stop_gap` script pubkeys with no associated
    +    /// transactions. `parallel_requests` specifies the max number of HTTP requests to make in
    +    /// parallel.
    +    ///
    +    /// [`ChainPosition`]: bdk_chain::sparse_chain::ChainPosition
    +    #[allow(clippy::result_large_err)] // FIXME
    +    fn scan<K: Ord + Clone>(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, Script)>>,
    +        txids: impl IntoIterator<Item = Txid>,
    +        outpoints: impl IntoIterator<Item = OutPoint>,
    +        stop_gap: usize,
    +        parallel_requests: usize,
    +    ) -> Result<KeychainScan<K, ConfirmationTime>, Error>;
    +
    +    /// Convenience method to call [`scan`] without requiring a keychain.
    +    ///
    +    /// [`scan`]: EsploraExt::scan
    +    #[allow(clippy::result_large_err)] // FIXME
    +    fn scan_without_keychain(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        misc_spks: impl IntoIterator<Item = Script>,
    +        txids: impl IntoIterator<Item = Txid>,
    +        outpoints: impl IntoIterator<Item = OutPoint>,
    +        parallel_requests: usize,
    +    ) -> Result<ChainGraph<ConfirmationTime>, Error> {
    +        let wallet_scan = self.scan(
    +            local_chain,
    +            [(
    +                (),
    +                misc_spks
    +                    .into_iter()
    +                    .enumerate()
    +                    .map(|(i, spk)| (i as u32, spk)),
    +            )]
    +            .into(),
    +            txids,
    +            outpoints,
    +            usize::MAX,
    +            parallel_requests,
    +        )?;
    +
    +        Ok(wallet_scan.update)
    +    }
    +}
    +
    +impl EsploraExt for esplora_client::BlockingClient {
    +    fn scan<K: Ord + Clone>(
    +        &self,
    +        local_chain: &BTreeMap<u32, BlockHash>,
    +        keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, Script)>>,
    +        txids: impl IntoIterator<Item = Txid>,
    +        outpoints: impl IntoIterator<Item = OutPoint>,
    +        stop_gap: usize,
    +        parallel_requests: usize,
    +    ) -> Result<KeychainScan<K, ConfirmationTime>, Error> {
    +        let parallel_requests = parallel_requests.max(1);
    +        let mut scan = KeychainScan::default();
    +        let update = &mut scan.update;
    +        let last_active_indices = &mut scan.last_active_indices;
    +
    +        for (&height, &original_hash) in local_chain.iter().rev() {
    +            let update_block_id = BlockId {
    +                height,
    +                hash: self.get_block_hash(height)?,
    +            };
    +            let _ = update
    +                .insert_checkpoint(update_block_id)
    +                .expect("cannot repeat height here");
    +            if update_block_id.hash == original_hash {
    +                break;
    +            }
    +        }
    +        let tip_at_start = BlockId {
    +            height: self.get_height()?,
    +            hash: self.get_tip_hash()?,
    +        };
    +        if let Err(failure) = update.insert_checkpoint(tip_at_start) {
    +            match failure {
    +                sparse_chain::InsertCheckpointError::HashNotMatching { .. } => {
    +                    // there has been a re-org before we started scanning. We haven't consumed any iterators so it's safe to recursively call.
    +                    return EsploraExt::scan(
    +                        self,
    +                        local_chain,
    +                        keychain_spks,
    +                        txids,
    +                        outpoints,
    +                        stop_gap,
    +                        parallel_requests,
    +                    );
    +                }
    +            }
    +        }
    +
    +        for (keychain, spks) in keychain_spks {
    +            let mut spks = spks.into_iter();
    +            let mut last_active_index = None;
    +            let mut empty_scripts = 0;
    +            type IndexWithTxs = (u32, Vec<esplora_client::Tx>);
    +
    +            loop {
    +                let handles = (0..parallel_requests)
    +                    .filter_map(
    +                        |_| -> Option<std::thread::JoinHandle<Result<IndexWithTxs, _>>> {
    +                            let (index, script) = spks.next()?;
    +                            let client = self.clone();
    +                            Some(std::thread::spawn(move || {
    +                                let mut related_txs = client.scripthash_txs(&script, None)?;
    +
    +                                let n_confirmed =
    +                                    related_txs.iter().filter(|tx| tx.status.confirmed).count();
    +                                // esplora pages on 25 confirmed transactions. If there's 25 or more we
    +                                // keep requesting to see if there's more.
    +                                if n_confirmed >= 25 {
    +                                    loop {
    +                                        let new_related_txs = client.scripthash_txs(
    +                                            &script,
    +                                            Some(related_txs.last().unwrap().txid),
    +                                        )?;
    +                                        let n = new_related_txs.len();
    +                                        related_txs.extend(new_related_txs);
    +                                        // we've reached the end
    +                                        if n < 25 {
    +                                            break;
    +                                        }
    +                                    }
    +                                }
    +
    +                                Result::<_, esplora_client::Error>::Ok((index, related_txs))
    +                            }))
    +                        },
    +                    )
    +                    .collect::<Vec<_>>();
    +
    +                let n_handles = handles.len();
    +
    +                for handle in handles {
    +                    let (index, related_txs) = handle.join().unwrap()?; // TODO: don't unwrap
    +                    if related_txs.is_empty() {
    +                        empty_scripts += 1;
    +                    } else {
    +                        last_active_index = Some(index);
    +                        empty_scripts = 0;
    +                    }
    +                    for tx in related_txs {
    +                        let confirmation_time =
    +                            map_confirmation_time(&tx.status, tip_at_start.height);
    +
    +                        if let Err(failure) = update.insert_tx(tx.to_tx(), confirmation_time) {
    +                            use bdk_chain::{
    +                                chain_graph::InsertTxError, sparse_chain::InsertTxError::*,
    +                            };
    +                            match failure {
    +                                InsertTxError::Chain(TxTooHigh { .. }) => {
    +                                    unreachable!("chain position already checked earlier")
    +                                }
    +                                InsertTxError::Chain(TxMovedUnexpectedly { .. })
    +                                | InsertTxError::UnresolvableConflict(_) => {
    +                                    /* implies reorg during scan. We deal with that below */
    +                                }
    +                            }
    +                        }
    +                    }
    +                }
    +
    +                if n_handles == 0 || empty_scripts >= stop_gap {
    +                    break;
    +                }
    +            }
    +
    +            if let Some(last_active_index) = last_active_index {
    +                last_active_indices.insert(keychain, last_active_index);
    +            }
    +        }
    +
    +        for txid in txids.into_iter() {
    +            let (tx, tx_status) = match (self.get_tx(&txid)?, self.get_tx_status(&txid)?) {
    +                (Some(tx), Some(tx_status)) => (tx, tx_status),
    +                _ => continue,
    +            };
    +
    +            let confirmation_time = map_confirmation_time(&tx_status, tip_at_start.height);
    +
    +            if let Err(failure) = update.insert_tx(tx, confirmation_time) {
    +                use bdk_chain::{chain_graph::InsertTxError, sparse_chain::InsertTxError::*};
    +                match failure {
    +                    InsertTxError::Chain(TxTooHigh { .. }) => {
    +                        unreachable!("chain position already checked earlier")
    +                    }
    +                    InsertTxError::Chain(TxMovedUnexpectedly { .. })
    +                    | InsertTxError::UnresolvableConflict(_) => {
    +                        /* implies reorg during scan. We deal with that below */
    +                    }
    +                }
    +            }
    +        }
    +
    +        for op in outpoints.into_iter() {
    +            let mut op_txs = Vec::with_capacity(2);
    +            if let (Some(tx), Some(tx_status)) =
    +                (self.get_tx(&op.txid)?, self.get_tx_status(&op.txid)?)
    +            {
    +                op_txs.push((tx, tx_status));
    +                if let Some(OutputStatus {
    +                    txid: Some(txid),
    +                    status: Some(spend_status),
    +                    ..
    +                }) = self.get_output_status(&op.txid, op.vout as _)?
    +                {
    +                    if let Some(spend_tx) = self.get_tx(&txid)? {
    +                        op_txs.push((spend_tx, spend_status));
    +                    }
    +                }
    +            }
    +
    +            for (tx, status) in op_txs {
    +                let confirmation_time = map_confirmation_time(&status, tip_at_start.height);
    +
    +                if let Err(failure) = update.insert_tx(tx, confirmation_time) {
    +                    use bdk_chain::{chain_graph::InsertTxError, sparse_chain::InsertTxError::*};
    +                    match failure {
    +                        InsertTxError::Chain(TxTooHigh { .. }) => {
    +                            unreachable!("chain position already checked earlier")
    +                        }
    +                        InsertTxError::Chain(TxMovedUnexpectedly { .. })
    +                        | InsertTxError::UnresolvableConflict(_) => {
    +                            /* implies reorg during scan. We deal with that below */
    +                        }
    +                    }
    +                }
    +            }
    +        }
    +
    +        let reorg_occurred = {
    +            if let Some(checkpoint) = update.chain().latest_checkpoint() {
    +                self.get_block_hash(checkpoint.height)? != checkpoint.hash
    +            } else {
    +                false
    +            }
    +        };
    +
    +        if reorg_occurred {
    +            // A reorg occurred so lets find out where all the txids we found are in the chain now.
    +            // XXX: collect required because of weird type naming issues
    +            let txids_found = update
    +                .chain()
    +                .txids()
    +                .map(|(_, txid)| *txid)
    +                .collect::<Vec<_>>();
    +            scan.update = EsploraExt::scan_without_keychain(
    +                self,
    +                local_chain,
    +                [],
    +                txids_found,
    +                [],
    +                parallel_requests,
    +            )?;
    +        }
    +
    +        Ok(scan)
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/lib.rs.html new file mode 100644 index 0000000000..afe1321511 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora/lib.rs.html @@ -0,0 +1,56 @@ +lib.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +
    #![doc = include_str!("../README.md")]
    +use bdk_chain::ConfirmationTime;
    +use esplora_client::TxStatus;
    +
    +pub use esplora_client;
    +
    +#[cfg(feature = "blocking")]
    +mod blocking_ext;
    +#[cfg(feature = "blocking")]
    +pub use blocking_ext::*;
    +
    +#[cfg(feature = "async")]
    +mod async_ext;
    +#[cfg(feature = "async")]
    +pub use async_ext::*;
    +
    +pub(crate) fn map_confirmation_time(
    +    tx_status: &TxStatus,
    +    height_at_start: u32,
    +) -> ConfirmationTime {
    +    match (tx_status.block_time, tx_status.block_height) {
    +        (Some(time), Some(height)) if height <= height_at_start => {
    +            ConfirmationTime::Confirmed { height, time }
    +        }
    +        _ => ConfirmationTime::Unconfirmed,
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora_wallet_example/main.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora_wallet_example/main.rs.html new file mode 100644 index 0000000000..ec32456bc9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_esplora_wallet_example/main.rs.html @@ -0,0 +1,194 @@ +main.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +
    use bdk::{
    +    bitcoin::{Address, Network},
    +    wallet::AddressIndex,
    +    SignOptions, Wallet,
    +};
    +use bdk_esplora::esplora_client;
    +use bdk_esplora::EsploraExt;
    +use bdk_file_store::KeychainStore;
    +use std::{io::Write, str::FromStr};
    +
    +const SEND_AMOUNT: u64 = 5000;
    +const STOP_GAP: usize = 50;
    +const PARALLEL_REQUESTS: usize = 5;
    +
    +fn main() -> Result<(), Box<dyn std::error::Error>> {
    +    let db_path = std::env::temp_dir().join("bdk-esplora-example");
    +    let db = KeychainStore::new_from_path(db_path)?;
    +    let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)";
    +    let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)";
    +
    +    let mut wallet = Wallet::new(
    +        external_descriptor,
    +        Some(internal_descriptor),
    +        db,
    +        Network::Testnet,
    +    )?;
    +
    +    let address = wallet.get_address(AddressIndex::New);
    +    println!("Generated Address: {}", address);
    +
    +    let balance = wallet.get_balance();
    +    println!("Wallet balance before syncing: {} sats", balance.total());
    +
    +    print!("Syncing...");
    +    // Scanning the chain...
    +    let esplora_url = "https://mempool.space/testnet/api";
    +    let client = esplora_client::Builder::new(esplora_url).build_blocking()?;
    +    let checkpoints = wallet.checkpoints();
    +    let spks = wallet
    +        .spks_of_all_keychains()
    +        .into_iter()
    +        .map(|(k, spks)| {
    +            let mut first = true;
    +            (
    +                k,
    +                spks.inspect(move |(spk_i, _)| {
    +                    if first {
    +                        first = false;
    +                        print!("\nScanning keychain [{:?}]:", k);
    +                    }
    +                    print!(" {}", spk_i);
    +                    let _ = std::io::stdout().flush();
    +                }),
    +            )
    +        })
    +        .collect();
    +    let update = client.scan(
    +        checkpoints,
    +        spks,
    +        core::iter::empty(),
    +        core::iter::empty(),
    +        STOP_GAP,
    +        PARALLEL_REQUESTS,
    +    )?;
    +    println!();
    +    wallet.apply_update(update)?;
    +    wallet.commit()?;
    +
    +    let balance = wallet.get_balance();
    +    println!("Wallet balance after syncing: {} sats", balance.total());
    +
    +    if balance.total() < SEND_AMOUNT {
    +        println!(
    +            "Please send at least {} sats to the receiving address",
    +            SEND_AMOUNT
    +        );
    +        std::process::exit(0);
    +    }
    +
    +    let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?;
    +
    +    let mut tx_builder = wallet.build_tx();
    +    tx_builder
    +        .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
    +        .enable_rbf();
    +
    +    let (mut psbt, _) = tx_builder.finish()?;
    +    let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    +    assert!(finalized);
    +
    +    let tx = psbt.extract_tx();
    +    client.broadcast(&tx)?;
    +    println!("Tx broadcasted! Txid: {}", tx.txid());
    +
    +    Ok(())
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_file_store/file_store.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_file_store/file_store.rs.html new file mode 100644 index 0000000000..268da4f35b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_file_store/file_store.rs.html @@ -0,0 +1,810 @@ +file_store.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +
    //! Module for persisting data on-disk.
    +//!
    +//! The star of the show is [`KeychainStore`] which maintains an append-only file of
    +//! [`KeychainChangeSet`]s which can be used to restore a [`KeychainTracker`].
    +use bdk_chain::{
    +    keychain::{KeychainChangeSet, KeychainTracker},
    +    sparse_chain,
    +};
    +use bincode::{DefaultOptions, Options};
    +use core::marker::PhantomData;
    +use std::{
    +    fs::{File, OpenOptions},
    +    io::{self, Read, Seek, Write},
    +    path::Path,
    +};
    +
    +/// BDK File Store magic bytes length.
    +const MAGIC_BYTES_LEN: usize = 12;
    +
    +/// BDK File Store magic bytes.
    +const MAGIC_BYTES: [u8; MAGIC_BYTES_LEN] = [98, 100, 107, 102, 115, 48, 48, 48, 48, 48, 48, 48];
    +
    +/// Persists an append only list of `KeychainChangeSet<K,P>` to a single file.
    +/// [`KeychainChangeSet<K,P>`] record the changes made to a [`KeychainTracker<K,P>`].
    +#[derive(Debug)]
    +pub struct KeychainStore<K, P> {
    +    db_file: File,
    +    changeset_type_params: core::marker::PhantomData<(K, P)>,
    +}
    +
    +fn bincode() -> impl bincode::Options {
    +    DefaultOptions::new().with_varint_encoding()
    +}
    +
    +impl<K, P> KeychainStore<K, P>
    +where
    +    K: Ord + Clone + core::fmt::Debug,
    +    P: sparse_chain::ChainPosition,
    +    KeychainChangeSet<K, P>: serde::Serialize + serde::de::DeserializeOwned,
    +{
    +    /// Creates a new store from a [`File`].
    +    ///
    +    /// The file must have been opened with read, write permissions.
    +    ///
    +    /// [`File`]: std::fs::File
    +    pub fn new(mut file: File) -> Result<Self, FileError> {
    +        file.rewind()?;
    +
    +        let mut magic_bytes = [0_u8; MAGIC_BYTES_LEN];
    +        file.read_exact(&mut magic_bytes)?;
    +
    +        if magic_bytes != MAGIC_BYTES {
    +            return Err(FileError::InvalidMagicBytes(magic_bytes));
    +        }
    +
    +        Ok(Self {
    +            db_file: file,
    +            changeset_type_params: Default::default(),
    +        })
    +    }
    +
    +    /// Creates or loads a a store from `db_path`. If no file exists there it will be created.
    +    pub fn new_from_path<D: AsRef<Path>>(db_path: D) -> Result<Self, FileError> {
    +        let already_exists = db_path.as_ref().exists();
    +
    +        let mut db_file = OpenOptions::new()
    +            .read(true)
    +            .write(true)
    +            .create(true)
    +            .open(db_path)?;
    +
    +        if !already_exists {
    +            db_file.write_all(&MAGIC_BYTES)?;
    +        }
    +
    +        Self::new(db_file)
    +    }
    +
    +    /// Iterates over the stored changeset from first to last changing the seek position at each
    +    /// iteration.
    +    ///
    +    /// The iterator may fail to read an entry and therefore return an error. However the first time
    +    /// it returns an error will be the last. After doing so the iterator will always yield `None`.
    +    ///
    +    /// **WARNING**: This method changes the write position in the underlying file. You should
    +    /// always iterate over all entries until `None` is returned if you want your next write to go
    +    /// at the end, otherwise you will write over existing enties.
    +    pub fn iter_changesets(&mut self) -> Result<EntryIter<'_, KeychainChangeSet<K, P>>, io::Error> {
    +        self.db_file
    +            .seek(io::SeekFrom::Start(MAGIC_BYTES_LEN as _))?;
    +
    +        Ok(EntryIter::new(&mut self.db_file))
    +    }
    +
    +    /// Loads all the changesets that have been stored as one giant changeset.
    +    ///
    +    /// This function returns a tuple of the aggregate changeset and a result which indicates
    +    /// whether an error occurred while reading or deserializing one of the entries. If so the
    +    /// changeset will consist of all of those it was able to read.
    +    ///
    +    /// You should usually check the error. In many applications it may make sense to do a full
    +    /// wallet scan with a stop gap after getting an error since it is likely that one of the
    +    /// changesets it was unable to read changed the derivation indicies of the tracker.
    +    ///
    +    /// **WARNING**: This method changes the write position of the underlying file. The next
    +    /// changeset will be written over the erroring entry (or the end of the file if none existed).
    +    pub fn aggregate_changeset(&mut self) -> (KeychainChangeSet<K, P>, Result<(), IterError>) {
    +        let mut changeset = KeychainChangeSet::default();
    +        let result = (|| {
    +            let iter_changeset = self.iter_changesets()?;
    +            for next_changeset in iter_changeset {
    +                changeset.append(next_changeset?);
    +            }
    +            Ok(())
    +        })();
    +
    +        (changeset, result)
    +    }
    +
    +    /// Reads and applies all the changesets stored sequentially to tracker, stopping when it fails
    +    /// to read the next one.
    +    ///
    +    /// **WARNING**: This method changes the write position of the underlying file. The next
    +    /// changeset will be written over the erroring entry (or the end of the file if none existed).
    +    pub fn load_into_keychain_tracker(
    +        &mut self,
    +        tracker: &mut KeychainTracker<K, P>,
    +    ) -> Result<(), IterError> {
    +        for changeset in self.iter_changesets()? {
    +            tracker.apply_changeset(changeset?)
    +        }
    +        Ok(())
    +    }
    +
    +    /// Append a new changeset to the file and truncate file to the end of the appended changeset.
    +    ///
    +    /// The truncation is to avoid the possibility of having a valid, but inconsistent changeset
    +    /// directly after the appended changeset.
    +    pub fn append_changeset(
    +        &mut self,
    +        changeset: &KeychainChangeSet<K, P>,
    +    ) -> Result<(), io::Error> {
    +        if changeset.is_empty() {
    +            return Ok(());
    +        }
    +
    +        bincode()
    +            .serialize_into(&mut self.db_file, changeset)
    +            .map_err(|e| match *e {
    +                bincode::ErrorKind::Io(inner) => inner,
    +                unexpected_err => panic!("unexpected bincode error: {}", unexpected_err),
    +            })?;
    +
    +        // truncate file after this changeset addition
    +        // if this is not done, data after this changeset may represent valid changesets, however
    +        // applying those changesets on top of this one may result in inconsistent state
    +        let pos = self.db_file.stream_position()?;
    +        self.db_file.set_len(pos)?;
    +
    +        // We want to make sure that derivation indexe changes are written to disk as soon as
    +        // possible so you know about the write failure before you give ou the address in the application.
    +        if !changeset.derivation_indices.is_empty() {
    +            self.db_file.sync_data()?;
    +        }
    +
    +        Ok(())
    +    }
    +}
    +
    +/// Error that occurs due to problems encountered with the file.
    +#[derive(Debug)]
    +pub enum FileError {
    +    /// IO error, this may mean that the file is too short.
    +    Io(io::Error),
    +    /// Magic bytes do not match expected.
    +    InvalidMagicBytes([u8; MAGIC_BYTES_LEN]),
    +}
    +
    +impl core::fmt::Display for FileError {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            Self::Io(e) => write!(f, "io error trying to read file: {}", e),
    +            Self::InvalidMagicBytes(b) => write!(
    +                f,
    +                "file has invalid magic bytes: expected={:?} got={:?}",
    +                MAGIC_BYTES, b
    +            ),
    +        }
    +    }
    +}
    +
    +impl From<io::Error> for FileError {
    +    fn from(value: io::Error) -> Self {
    +        Self::Io(value)
    +    }
    +}
    +
    +impl std::error::Error for FileError {}
    +
    +/// Error type for [`EntryIter`].
    +#[derive(Debug)]
    +pub enum IterError {
    +    /// Failure to read from file.
    +    Io(io::Error),
    +    /// Failure to decode data from file.
    +    Bincode(bincode::ErrorKind),
    +}
    +
    +impl core::fmt::Display for IterError {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            IterError::Io(e) => write!(f, "io error trying to read entry {}", e),
    +            IterError::Bincode(e) => write!(f, "bincode error while reading entry {}", e),
    +        }
    +    }
    +}
    +
    +impl std::error::Error for IterError {}
    +
    +/// Iterator over entries in a file store.
    +///
    +/// Reads and returns an entry each time [`next`] is called. If an error occurs while reading the
    +/// iterator will yield a `Result::Err(_)` instead and then `None` for the next call to `next`.
    +///
    +/// [`next`]: Self::next
    +pub struct EntryIter<'a, V> {
    +    db_file: &'a mut File,
    +    types: PhantomData<V>,
    +    error_exit: bool,
    +}
    +
    +impl<'a, V> EntryIter<'a, V> {
    +    pub fn new(db_file: &'a mut File) -> Self {
    +        Self {
    +            db_file,
    +            types: PhantomData,
    +            error_exit: false,
    +        }
    +    }
    +}
    +
    +impl<'a, V> Iterator for EntryIter<'a, V>
    +where
    +    V: serde::de::DeserializeOwned,
    +{
    +    type Item = Result<V, IterError>;
    +
    +    fn next(&mut self) -> Option<Self::Item> {
    +        let result = (|| {
    +            let pos = self.db_file.stream_position()?;
    +
    +            match bincode().deserialize_from(&mut self.db_file) {
    +                Ok(changeset) => Ok(Some(changeset)),
    +                Err(e) => {
    +                    if let bincode::ErrorKind::Io(inner) = &*e {
    +                        if inner.kind() == io::ErrorKind::UnexpectedEof {
    +                            let eof = self.db_file.seek(io::SeekFrom::End(0))?;
    +                            if pos == eof {
    +                                return Ok(None);
    +                            }
    +                        }
    +                    }
    +
    +                    self.db_file.seek(io::SeekFrom::Start(pos))?;
    +                    Err(IterError::Bincode(*e))
    +                }
    +            }
    +        })();
    +
    +        let result = result.transpose();
    +
    +        if let Some(Err(_)) = &result {
    +            self.error_exit = true;
    +        }
    +
    +        result
    +    }
    +}
    +
    +impl From<io::Error> for IterError {
    +    fn from(value: io::Error) -> Self {
    +        IterError::Io(value)
    +    }
    +}
    +
    +#[cfg(test)]
    +mod test {
    +    use super::*;
    +    use bdk_chain::{
    +        keychain::{DerivationAdditions, KeychainChangeSet},
    +        TxHeight,
    +    };
    +    use std::{
    +        io::{Read, Write},
    +        vec::Vec,
    +    };
    +    use tempfile::NamedTempFile;
    +    #[derive(
    +        Debug,
    +        Clone,
    +        Copy,
    +        PartialOrd,
    +        Ord,
    +        PartialEq,
    +        Eq,
    +        Hash,
    +        serde::Serialize,
    +        serde::Deserialize,
    +    )]
    +    enum TestKeychain {
    +        External,
    +        Internal,
    +    }
    +
    +    impl core::fmt::Display for TestKeychain {
    +        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    +            match self {
    +                Self::External => write!(f, "external"),
    +                Self::Internal => write!(f, "internal"),
    +            }
    +        }
    +    }
    +
    +    #[test]
    +    fn magic_bytes() {
    +        assert_eq!(&MAGIC_BYTES, "bdkfs0000000".as_bytes());
    +    }
    +
    +    #[test]
    +    fn new_fails_if_file_is_too_short() {
    +        let mut file = NamedTempFile::new().unwrap();
    +        file.write_all(&MAGIC_BYTES[..MAGIC_BYTES_LEN - 1])
    +            .expect("should write");
    +
    +        match KeychainStore::<TestKeychain, TxHeight>::new(file.reopen().unwrap()) {
    +            Err(FileError::Io(e)) => assert_eq!(e.kind(), std::io::ErrorKind::UnexpectedEof),
    +            unexpected => panic!("unexpected result: {:?}", unexpected),
    +        };
    +    }
    +
    +    #[test]
    +    fn new_fails_if_magic_bytes_are_invalid() {
    +        let invalid_magic_bytes = "ldkfs0000000";
    +
    +        let mut file = NamedTempFile::new().unwrap();
    +        file.write_all(invalid_magic_bytes.as_bytes())
    +            .expect("should write");
    +
    +        match KeychainStore::<TestKeychain, TxHeight>::new(file.reopen().unwrap()) {
    +            Err(FileError::InvalidMagicBytes(b)) => {
    +                assert_eq!(b, invalid_magic_bytes.as_bytes())
    +            }
    +            unexpected => panic!("unexpected result: {:?}", unexpected),
    +        };
    +    }
    +
    +    #[test]
    +    fn append_changeset_truncates_invalid_bytes() {
    +        // initial data to write to file (magic bytes + invalid data)
    +        let mut data = [255_u8; 2000];
    +        data[..MAGIC_BYTES_LEN].copy_from_slice(&MAGIC_BYTES);
    +
    +        let changeset = KeychainChangeSet {
    +            derivation_indices: DerivationAdditions(
    +                vec![(TestKeychain::External, 42)].into_iter().collect(),
    +            ),
    +            chain_graph: Default::default(),
    +        };
    +
    +        let mut file = NamedTempFile::new().unwrap();
    +        file.write_all(&data).expect("should write");
    +
    +        let mut store = KeychainStore::<TestKeychain, TxHeight>::new(file.reopen().unwrap())
    +            .expect("should open");
    +        match store.iter_changesets().expect("seek should succeed").next() {
    +            Some(Err(IterError::Bincode(_))) => {}
    +            unexpected_res => panic!("unexpected result: {:?}", unexpected_res),
    +        }
    +
    +        store.append_changeset(&changeset).expect("should append");
    +
    +        drop(store);
    +
    +        let got_bytes = {
    +            let mut buf = Vec::new();
    +            file.reopen()
    +                .unwrap()
    +                .read_to_end(&mut buf)
    +                .expect("should read");
    +            buf
    +        };
    +
    +        let expected_bytes = {
    +            let mut buf = MAGIC_BYTES.to_vec();
    +            DefaultOptions::new()
    +                .with_varint_encoding()
    +                .serialize_into(&mut buf, &changeset)
    +                .expect("should encode");
    +            buf
    +        };
    +
    +        assert_eq!(got_bytes, expected_bytes);
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_file_store/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_file_store/lib.rs.html new file mode 100644 index 0000000000..23c9fa4689 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_file_store/lib.rs.html @@ -0,0 +1,66 @@ +lib.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +
    #![doc = include_str!("../README.md")]
    +mod file_store;
    +use bdk_chain::{
    +    keychain::{KeychainChangeSet, KeychainTracker, PersistBackend},
    +    sparse_chain::ChainPosition,
    +};
    +pub use file_store::*;
    +
    +impl<K, P> PersistBackend<K, P> for KeychainStore<K, P>
    +where
    +    K: Ord + Clone + core::fmt::Debug,
    +    P: ChainPosition,
    +    KeychainChangeSet<K, P>: serde::Serialize + serde::de::DeserializeOwned,
    +{
    +    type WriteError = std::io::Error;
    +
    +    type LoadError = IterError;
    +
    +    fn append_changeset(
    +        &mut self,
    +        changeset: &KeychainChangeSet<K, P>,
    +    ) -> Result<(), Self::WriteError> {
    +        KeychainStore::append_changeset(self, changeset)
    +    }
    +
    +    fn load_into_keychain_tracker(
    +        &mut self,
    +        tracker: &mut KeychainTracker<K, P>,
    +    ) -> Result<(), Self::LoadError> {
    +        KeychainStore::load_into_keychain_tracker(self, tracker)
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/lib.rs.html new file mode 100644 index 0000000000..277fc1b33c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/lib.rs.html @@ -0,0 +1,876 @@ +lib.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +
    #![allow(unused)]
    +#![allow(missing_docs)]
    +#![allow(clippy::all)] // FIXME
    +//! A spending plan or *plan* for short is a representation of a particular spending path on a
    +//! descriptor. This allows us to analayze a choice of spending path without producing any
    +//! signatures or other witness data for it.
    +//!
    +//! To make a plan you provide the descriptor with "assets" like which keys you are able to use, hash
    +//! pre-images you have access to, the current block height etc.
    +//!
    +//! Once you've got a plan it can tell you its expected satisfaction weight which can be useful for
    +//! doing coin selection. Furthermore it provides which subset of those keys and hash pre-images you
    +//! will actually need as well as what locktime or sequence number you need to set.
    +//!
    +//! Once you've obstained signatures, hash pre-images etc required by the plan, it can create a
    +//! witness/script_sig for the input.
    +use bdk_chain::{bitcoin, collections::*, miniscript};
    +use bitcoin::{
    +    blockdata::{locktime::LockTime, transaction::Sequence},
    +    hashes::{hash160, ripemd160, sha256},
    +    secp256k1::Secp256k1,
    +    util::{
    +        address::WitnessVersion,
    +        bip32::{DerivationPath, Fingerprint, KeySource},
    +        taproot::{LeafVersion, TapBranchHash, TapLeafHash},
    +    },
    +    EcdsaSig, SchnorrSig, Script, TxIn, Witness,
    +};
    +use miniscript::{
    +    descriptor::{InnerXKey, Tr},
    +    hash256, DefiniteDescriptorKey, Descriptor, DescriptorPublicKey, ScriptContext, ToPublicKey,
    +};
    +
    +pub(crate) fn varint_len(v: usize) -> usize {
    +    bitcoin::VarInt(v as u64).len() as usize
    +}
    +
    +mod plan_impls;
    +mod requirements;
    +mod template;
    +pub use requirements::*;
    +pub use template::PlanKey;
    +use template::TemplateItem;
    +
    +#[derive(Clone, Debug)]
    +enum TrSpend {
    +    KeySpend,
    +    LeafSpend {
    +        script: Script,
    +        leaf_version: LeafVersion,
    +    },
    +}
    +
    +#[derive(Clone, Debug)]
    +enum Target {
    +    Legacy,
    +    Segwitv0 {
    +        script_code: Script,
    +    },
    +    Segwitv1 {
    +        tr: Tr<DefiniteDescriptorKey>,
    +        tr_plan: TrSpend,
    +    },
    +}
    +
    +impl Target {}
    +
    +#[derive(Clone, Debug)]
    +/// A plan represents a particular spending path for a descriptor.
    +///
    +/// See the module level documentation for more info.
    +pub struct Plan<AK> {
    +    template: Vec<TemplateItem<AK>>,
    +    target: Target,
    +    set_locktime: Option<LockTime>,
    +    set_sequence: Option<Sequence>,
    +}
    +
    +impl Default for Target {
    +    fn default() -> Self {
    +        Target::Legacy
    +    }
    +}
    +
    +#[derive(Clone, Debug, Default)]
    +/// Signatures and hash pre-images that can be used to complete a plan.
    +pub struct SatisfactionMaterial {
    +    /// Schnorr signautres under their keys
    +    pub schnorr_sigs: BTreeMap<DefiniteDescriptorKey, SchnorrSig>,
    +    /// ECDSA signatures under their keys
    +    pub ecdsa_sigs: BTreeMap<DefiniteDescriptorKey, EcdsaSig>,
    +    /// SHA256 pre-images under their images
    +    pub sha256_preimages: BTreeMap<sha256::Hash, Vec<u8>>,
    +    /// hash160 pre-images under their images
    +    pub hash160_preimages: BTreeMap<hash160::Hash, Vec<u8>>,
    +    /// hash256 pre-images under their images
    +    pub hash256_preimages: BTreeMap<hash256::Hash, Vec<u8>>,
    +    /// ripemd160 pre-images under their images
    +    pub ripemd160_preimages: BTreeMap<ripemd160::Hash, Vec<u8>>,
    +}
    +
    +impl<Ak> Plan<Ak>
    +where
    +    Ak: Clone,
    +{
    +    /// The expected satisfaction weight for the plan if it is completed.
    +    pub fn expected_weight(&self) -> usize {
    +        let script_sig_size = match self.target {
    +            Target::Legacy => unimplemented!(), // self
    +            // .template
    +            // .iter()
    +            // .map(|step| {
    +            //     let size = step.expected_size();
    +            //     size + push_opcode_size(size)
    +            // })
    +            // .sum()
    +            Target::Segwitv0 { .. } | Target::Segwitv1 { .. } => 1,
    +        };
    +        let witness_elem_sizes: Option<Vec<usize>> = match &self.target {
    +            Target::Legacy => None,
    +            Target::Segwitv0 { .. } => Some(
    +                self.template
    +                    .iter()
    +                    .map(|step| step.expected_size())
    +                    .collect(),
    +            ),
    +            Target::Segwitv1 { tr, tr_plan } => {
    +                let mut witness_elems = self
    +                    .template
    +                    .iter()
    +                    .map(|step| step.expected_size())
    +                    .collect::<Vec<_>>();
    +
    +                if let TrSpend::LeafSpend {
    +                    script,
    +                    leaf_version,
    +                } = tr_plan
    +                {
    +                    let control_block = tr
    +                        .spend_info()
    +                        .control_block(&(script.clone(), *leaf_version))
    +                        .expect("must exist");
    +                    witness_elems.push(script.len());
    +                    witness_elems.push(control_block.size());
    +                }
    +
    +                Some(witness_elems)
    +            }
    +        };
    +
    +        let witness_size: usize = match witness_elem_sizes {
    +            Some(elems) => {
    +                varint_len(elems.len())
    +                    + elems
    +                        .into_iter()
    +                        .map(|elem| varint_len(elem) + elem)
    +                        .sum::<usize>()
    +            }
    +            None => 0,
    +        };
    +
    +        script_sig_size * 4 + witness_size
    +    }
    +
    +    pub fn requirements(&self) -> Requirements<Ak> {
    +        match self.try_complete(&SatisfactionMaterial::default()) {
    +            PlanState::Complete { .. } => Requirements::default(),
    +            PlanState::Incomplete(requirements) => requirements,
    +        }
    +    }
    +
    +    pub fn try_complete(&self, auth_data: &SatisfactionMaterial) -> PlanState<Ak> {
    +        let unsatisfied_items = self
    +            .template
    +            .iter()
    +            .filter(|step| match step {
    +                TemplateItem::Sign(key) => {
    +                    !auth_data.schnorr_sigs.contains_key(&key.descriptor_key)
    +                }
    +                TemplateItem::Hash160(image) => !auth_data.hash160_preimages.contains_key(image),
    +                TemplateItem::Hash256(image) => !auth_data.hash256_preimages.contains_key(image),
    +                TemplateItem::Sha256(image) => !auth_data.sha256_preimages.contains_key(image),
    +                TemplateItem::Ripemd160(image) => {
    +                    !auth_data.ripemd160_preimages.contains_key(image)
    +                }
    +                TemplateItem::Pk { .. } | TemplateItem::One | TemplateItem::Zero => false,
    +            })
    +            .collect::<Vec<_>>();
    +
    +        if unsatisfied_items.is_empty() {
    +            let mut witness = self
    +                .template
    +                .iter()
    +                .flat_map(|step| step.to_witness_stack(&auth_data))
    +                .collect::<Vec<_>>();
    +            match &self.target {
    +                Target::Segwitv0 { .. } => todo!(),
    +                Target::Legacy => todo!(),
    +                Target::Segwitv1 {
    +                    tr_plan: TrSpend::KeySpend,
    +                    ..
    +                } => PlanState::Complete {
    +                    final_script_sig: None,
    +                    final_script_witness: Some(Witness::from_vec(witness)),
    +                },
    +                Target::Segwitv1 {
    +                    tr,
    +                    tr_plan:
    +                        TrSpend::LeafSpend {
    +                            script,
    +                            leaf_version,
    +                        },
    +                } => {
    +                    let spend_info = tr.spend_info();
    +                    let control_block = spend_info
    +                        .control_block(&(script.clone(), *leaf_version))
    +                        .expect("must exist");
    +                    witness.push(script.clone().into_bytes());
    +                    witness.push(control_block.serialize());
    +
    +                    PlanState::Complete {
    +                        final_script_sig: None,
    +                        final_script_witness: Some(Witness::from_vec(witness)),
    +                    }
    +                }
    +            }
    +        } else {
    +            let mut requirements = Requirements::default();
    +
    +            match &self.target {
    +                Target::Legacy => {
    +                    todo!()
    +                }
    +                Target::Segwitv0 { .. } => {
    +                    todo!()
    +                }
    +                Target::Segwitv1 { tr, tr_plan } => {
    +                    let spend_info = tr.spend_info();
    +                    match tr_plan {
    +                        TrSpend::KeySpend => match &self.template[..] {
    +                            [TemplateItem::Sign(ref plan_key)] => {
    +                                requirements.signatures = RequiredSignatures::TapKey {
    +                                    merkle_root: spend_info.merkle_root(),
    +                                    plan_key: plan_key.clone(),
    +                                };
    +                            }
    +                            _ => unreachable!("tapkey spend will always have only one sign step"),
    +                        },
    +                        TrSpend::LeafSpend {
    +                            script,
    +                            leaf_version,
    +                        } => {
    +                            let leaf_hash = TapLeafHash::from_script(&script, *leaf_version);
    +                            requirements.signatures = RequiredSignatures::TapScript {
    +                                leaf_hash,
    +                                plan_keys: vec![],
    +                            }
    +                        }
    +                    }
    +                }
    +            }
    +
    +            let required_signatures = match requirements.signatures {
    +                RequiredSignatures::Legacy { .. } => todo!(),
    +                RequiredSignatures::Segwitv0 { .. } => todo!(),
    +                RequiredSignatures::TapKey { .. } => return PlanState::Incomplete(requirements),
    +                RequiredSignatures::TapScript {
    +                    plan_keys: ref mut keys,
    +                    ..
    +                } => keys,
    +            };
    +
    +            for step in unsatisfied_items {
    +                match step {
    +                    TemplateItem::Sign(plan_key) => {
    +                        required_signatures.push(plan_key.clone());
    +                    }
    +                    TemplateItem::Hash160(image) => {
    +                        requirements.hash160_images.insert(image.clone());
    +                    }
    +                    TemplateItem::Hash256(image) => {
    +                        requirements.hash256_images.insert(image.clone());
    +                    }
    +                    TemplateItem::Sha256(image) => {
    +                        requirements.sha256_images.insert(image.clone());
    +                    }
    +                    TemplateItem::Ripemd160(image) => {
    +                        requirements.ripemd160_images.insert(image.clone());
    +                    }
    +                    TemplateItem::Pk { .. } | TemplateItem::One | TemplateItem::Zero => { /* no requirements */
    +                    }
    +                }
    +            }
    +
    +            PlanState::Incomplete(requirements)
    +        }
    +    }
    +
    +    /// Witness version for the plan
    +    pub fn witness_version(&self) -> Option<WitnessVersion> {
    +        match self.target {
    +            Target::Legacy => None,
    +            Target::Segwitv0 { .. } => Some(WitnessVersion::V0),
    +            Target::Segwitv1 { .. } => Some(WitnessVersion::V1),
    +        }
    +    }
    +
    +    /// The minimum required locktime height or time on the transaction using the plan.
    +    pub fn required_locktime(&self) -> Option<LockTime> {
    +        self.set_locktime.clone()
    +    }
    +
    +    /// The minimum required sequence (height or time) on the input to satisfy the plan
    +    pub fn required_sequence(&self) -> Option<Sequence> {
    +        self.set_sequence.clone()
    +    }
    +
    +    /// The minmum required transaction version required on the transaction using the plan.
    +    pub fn min_version(&self) -> Option<u32> {
    +        if let Some(_) = self.set_sequence {
    +            Some(2)
    +        } else {
    +            Some(1)
    +        }
    +    }
    +}
    +
    +/// The returned value from [`Plan::try_complete`].
    +pub enum PlanState<Ak> {
    +    /// The plan is complete
    +    Complete {
    +        /// The script sig that should be set on the input
    +        final_script_sig: Option<Script>,
    +        /// The witness that should be set on the input
    +        final_script_witness: Option<Witness>,
    +    },
    +    Incomplete(Requirements<Ak>),
    +}
    +
    +#[derive(Clone, Debug)]
    +pub struct Assets<K> {
    +    pub keys: Vec<K>,
    +    pub txo_age: Option<Sequence>,
    +    pub max_locktime: Option<LockTime>,
    +    pub sha256: Vec<sha256::Hash>,
    +    pub hash256: Vec<hash256::Hash>,
    +    pub ripemd160: Vec<ripemd160::Hash>,
    +    pub hash160: Vec<hash160::Hash>,
    +}
    +
    +impl<K> Default for Assets<K> {
    +    fn default() -> Self {
    +        Self {
    +            keys: Default::default(),
    +            txo_age: Default::default(),
    +            max_locktime: Default::default(),
    +            sha256: Default::default(),
    +            hash256: Default::default(),
    +            ripemd160: Default::default(),
    +            hash160: Default::default(),
    +        }
    +    }
    +}
    +
    +pub trait CanDerive {
    +    fn can_derive(&self, key: &DefiniteDescriptorKey) -> Option<DerivationPath>;
    +}
    +
    +impl CanDerive for KeySource {
    +    fn can_derive(&self, key: &DefiniteDescriptorKey) -> Option<DerivationPath> {
    +        match DescriptorPublicKey::from(key.clone()) {
    +            DescriptorPublicKey::Single(single_pub) => {
    +                path_to_child(self, single_pub.origin.as_ref()?, None)
    +            }
    +            DescriptorPublicKey::XPub(dxk) => {
    +                let origin = dxk.origin.clone().unwrap_or_else(|| {
    +                    let secp = Secp256k1::signing_only();
    +                    (dxk.xkey.xkey_fingerprint(&secp), DerivationPath::master())
    +                });
    +
    +                path_to_child(self, &origin, Some(&dxk.derivation_path))
    +            }
    +        }
    +    }
    +}
    +
    +impl CanDerive for DescriptorPublicKey {
    +    fn can_derive(&self, key: &DefiniteDescriptorKey) -> Option<DerivationPath> {
    +        match (self, DescriptorPublicKey::from(key.clone())) {
    +            (parent, child) if parent == &child => Some(DerivationPath::master()),
    +            (DescriptorPublicKey::XPub(parent), _) => {
    +                let origin = parent.origin.clone().unwrap_or_else(|| {
    +                    let secp = Secp256k1::signing_only();
    +                    (
    +                        parent.xkey.xkey_fingerprint(&secp),
    +                        DerivationPath::master(),
    +                    )
    +                });
    +                KeySource::from(origin).can_derive(key)
    +            }
    +            _ => None,
    +        }
    +    }
    +}
    +
    +fn path_to_child(
    +    parent: &KeySource,
    +    child_origin: &(Fingerprint, DerivationPath),
    +    child_derivation: Option<&DerivationPath>,
    +) -> Option<DerivationPath> {
    +    if parent.0 == child_origin.0 {
    +        let mut remaining_derivation =
    +            DerivationPath::from(child_origin.1[..].strip_prefix(&parent.1[..])?);
    +        remaining_derivation =
    +            remaining_derivation.extend(child_derivation.unwrap_or(&DerivationPath::master()));
    +        Some(remaining_derivation)
    +    } else {
    +        None
    +    }
    +}
    +
    +pub fn plan_satisfaction<Ak>(
    +    desc: &Descriptor<DefiniteDescriptorKey>,
    +    assets: &Assets<Ak>,
    +) -> Option<Plan<Ak>>
    +where
    +    Ak: CanDerive + Clone,
    +{
    +    match desc {
    +        Descriptor::Bare(_) => todo!(),
    +        Descriptor::Pkh(_) => todo!(),
    +        Descriptor::Wpkh(_) => todo!(),
    +        Descriptor::Sh(_) => todo!(),
    +        Descriptor::Wsh(_) => todo!(),
    +        Descriptor::Tr(tr) => crate::plan_impls::plan_satisfaction_tr(tr, assets),
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/plan_impls.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/plan_impls.rs.html new file mode 100644 index 0000000000..ea027ec39f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/plan_impls.rs.html @@ -0,0 +1,648 @@ +plan_impls.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +
    use bdk_chain::{bitcoin, miniscript};
    +use bitcoin::locktime::{Height, Time};
    +use miniscript::Terminal;
    +
    +use super::*;
    +
    +impl<Ak> TermPlan<Ak> {
    +    fn combine(self, other: Self) -> Option<Self> {
    +        let min_locktime = {
    +            match (self.min_locktime, other.min_locktime) {
    +                (Some(lhs), Some(rhs)) => {
    +                    if lhs.is_same_unit(rhs) {
    +                        Some(if lhs.to_consensus_u32() > rhs.to_consensus_u32() {
    +                            lhs
    +                        } else {
    +                            rhs
    +                        })
    +                    } else {
    +                        return None;
    +                    }
    +                }
    +                _ => self.min_locktime.or(other.min_locktime),
    +            }
    +        };
    +
    +        let min_sequence = {
    +            match (self.min_sequence, other.min_sequence) {
    +                (Some(lhs), Some(rhs)) => {
    +                    if lhs.is_height_locked() == rhs.is_height_locked() {
    +                        Some(if lhs.to_consensus_u32() > rhs.to_consensus_u32() {
    +                            lhs
    +                        } else {
    +                            rhs
    +                        })
    +                    } else {
    +                        return None;
    +                    }
    +                }
    +                _ => self.min_sequence.or(other.min_sequence),
    +            }
    +        };
    +
    +        let mut template = self.template;
    +        template.extend(other.template);
    +
    +        Some(Self {
    +            min_locktime,
    +            min_sequence,
    +            template,
    +        })
    +    }
    +
    +    pub(crate) fn expected_size(&self) -> usize {
    +        self.template.iter().map(|step| step.expected_size()).sum()
    +    }
    +}
    +
    +// impl crate::descriptor::Pkh<DefiniteDescriptorKey> {
    +//     pub(crate) fn plan_satisfaction<Ak>(&self, assets: &Assets<Ak>) -> Option<Plan<Ak>>
    +//     where
    +//         Ak: CanDerive + Clone,
    +//     {
    +//         let (asset_key, derivation_hint) = assets.keys.iter().find_map(|asset_key| {
    +//             let derivation_hint = asset_key.can_derive(self.as_inner())?;
    +//             Some((asset_key, derivation_hint))
    +//         })?;
    +
    +//         Some(Plan {
    +//             template: vec![TemplateItem::Sign(PlanKey {
    +//                 asset_key: asset_key.clone(),
    +//                 descriptor_key: self.as_inner().clone(),
    +//                 derivation_hint,
    +//             })],
    +//             target: Target::Legacy,
    +//             set_locktime: None,
    +//             set_sequence: None,
    +//         })
    +//     }
    +// }
    +
    +// impl crate::descriptor::Wpkh<DefiniteDescriptorKey> {
    +//     pub(crate) fn plan_satisfaction<Ak>(&self, assets: &Assets<Ak>) -> Option<Plan<Ak>>
    +//     where
    +//         Ak: CanDerive + Clone,
    +//     {
    +//         let (asset_key, derivation_hint) = assets.keys.iter().find_map(|asset_key| {
    +//             let derivation_hint = asset_key.can_derive(self.as_inner())?;
    +//             Some((asset_key, derivation_hint))
    +//         })?;
    +
    +//         Some(Plan {
    +//             template: vec![TemplateItem::Sign(PlanKey {
    +//                 asset_key: asset_key.clone(),
    +//                 descriptor_key: self.as_inner().clone(),
    +//                 derivation_hint,
    +//             })],
    +//             target: Target::Segwitv0,
    +//             set_locktime: None,
    +//             set_sequence: None,
    +//         })
    +//     }
    +// }
    +
    +pub(crate) fn plan_satisfaction_tr<Ak>(
    +    tr: &miniscript::descriptor::Tr<DefiniteDescriptorKey>,
    +    assets: &Assets<Ak>,
    +) -> Option<Plan<Ak>>
    +where
    +    Ak: CanDerive + Clone,
    +{
    +    let key_path_spend = assets.keys.iter().find_map(|asset_key| {
    +        let derivation_hint = asset_key.can_derive(tr.internal_key())?;
    +        Some((asset_key, derivation_hint))
    +    });
    +
    +    if let Some((asset_key, derivation_hint)) = key_path_spend {
    +        return Some(Plan {
    +            template: vec![TemplateItem::Sign(PlanKey {
    +                asset_key: asset_key.clone(),
    +                descriptor_key: tr.internal_key().clone(),
    +                derivation_hint,
    +            })],
    +            target: Target::Segwitv1 {
    +                tr: tr.clone(),
    +                tr_plan: TrSpend::KeySpend,
    +            },
    +            set_locktime: None,
    +            set_sequence: None,
    +        });
    +    }
    +
    +    let mut plans = tr
    +        .iter_scripts()
    +        .filter_map(|(_, ms)| Some((ms, (plan_steps(&ms.node, assets)?))))
    +        .collect::<Vec<_>>();
    +
    +    plans.sort_by_cached_key(|(_, plan)| plan.expected_size());
    +
    +    let (script, best_plan) = plans.into_iter().next()?;
    +
    +    Some(Plan {
    +        target: Target::Segwitv1 {
    +            tr: tr.clone(),
    +            tr_plan: TrSpend::LeafSpend {
    +                script: script.encode(),
    +                leaf_version: LeafVersion::TapScript,
    +            },
    +        },
    +        set_locktime: best_plan.min_locktime.clone(),
    +        set_sequence: best_plan.min_sequence.clone(),
    +        template: best_plan.template,
    +    })
    +}
    +
    +#[derive(Debug)]
    +struct TermPlan<Ak> {
    +    pub min_locktime: Option<LockTime>,
    +    pub min_sequence: Option<Sequence>,
    +    pub template: Vec<TemplateItem<Ak>>,
    +}
    +
    +impl<Ak> TermPlan<Ak> {
    +    fn new(template: Vec<TemplateItem<Ak>>) -> Self {
    +        TermPlan {
    +            template,
    +            ..Default::default()
    +        }
    +    }
    +}
    +
    +impl<Ak> Default for TermPlan<Ak> {
    +    fn default() -> Self {
    +        Self {
    +            min_locktime: Default::default(),
    +            min_sequence: Default::default(),
    +            template: Default::default(),
    +        }
    +    }
    +}
    +
    +fn plan_steps<Ak: Clone + CanDerive, Ctx: ScriptContext>(
    +    term: &Terminal<DefiniteDescriptorKey, Ctx>,
    +    assets: &Assets<Ak>,
    +) -> Option<TermPlan<Ak>> {
    +    match term {
    +        Terminal::True => Some(TermPlan::new(vec![])),
    +        Terminal::False => return None,
    +        Terminal::PkH(key) => {
    +            let (asset_key, derivation_hint) = assets
    +                .keys
    +                .iter()
    +                .find_map(|asset_key| Some((asset_key, asset_key.can_derive(key)?)))?;
    +            Some(TermPlan::new(vec![
    +                TemplateItem::Sign(PlanKey {
    +                    asset_key: asset_key.clone(),
    +                    derivation_hint,
    +                    descriptor_key: key.clone(),
    +                }),
    +                TemplateItem::Pk { key: key.clone() },
    +            ]))
    +        }
    +        Terminal::PkK(key) => {
    +            let (asset_key, derivation_hint) = assets
    +                .keys
    +                .iter()
    +                .find_map(|asset_key| Some((asset_key, asset_key.can_derive(key)?)))?;
    +            Some(TermPlan::new(vec![TemplateItem::Sign(PlanKey {
    +                asset_key: asset_key.clone(),
    +                derivation_hint,
    +                descriptor_key: key.clone(),
    +            })]))
    +        }
    +        Terminal::RawPkH(_pk_hash) => {
    +            /* TODO */
    +            None
    +        }
    +        Terminal::After(locktime) => {
    +            let max_locktime = assets.max_locktime?;
    +            let locktime = LockTime::from(locktime);
    +            let (height, time) = match max_locktime {
    +                LockTime::Blocks(height) => (height, Time::from_consensus(0).unwrap()),
    +                LockTime::Seconds(seconds) => (Height::from_consensus(0).unwrap(), seconds),
    +            };
    +            if max_locktime.is_satisfied_by(height, time) {
    +                Some(TermPlan {
    +                    min_locktime: Some(locktime),
    +                    ..Default::default()
    +                })
    +            } else {
    +                None
    +            }
    +        }
    +        Terminal::Older(older) => {
    +            // FIXME: older should be a height or time not a sequence.
    +            let max_sequence = assets.txo_age?;
    +            //TODO: this whole thing is probably wrong but upstream should provide a way of
    +            // doing it properly.
    +            if max_sequence.is_height_locked() == older.is_height_locked() {
    +                if max_sequence.to_consensus_u32() >= older.to_consensus_u32() {
    +                    Some(TermPlan {
    +                        min_sequence: Some(*older),
    +                        ..Default::default()
    +                    })
    +                } else {
    +                    None
    +                }
    +            } else {
    +                None
    +            }
    +        }
    +        Terminal::Sha256(image) => {
    +            if assets.sha256.contains(&image) {
    +                Some(TermPlan::new(vec![TemplateItem::Sha256(image.clone())]))
    +            } else {
    +                None
    +            }
    +        }
    +        Terminal::Hash256(image) => {
    +            if assets.hash256.contains(image) {
    +                Some(TermPlan::new(vec![TemplateItem::Hash256(image.clone())]))
    +            } else {
    +                None
    +            }
    +        }
    +        Terminal::Ripemd160(image) => {
    +            if assets.ripemd160.contains(&image) {
    +                Some(TermPlan::new(vec![TemplateItem::Ripemd160(image.clone())]))
    +            } else {
    +                None
    +            }
    +        }
    +        Terminal::Hash160(image) => {
    +            if assets.hash160.contains(&image) {
    +                Some(TermPlan::new(vec![TemplateItem::Hash160(image.clone())]))
    +            } else {
    +                None
    +            }
    +        }
    +        Terminal::Alt(ms)
    +        | Terminal::Swap(ms)
    +        | Terminal::Check(ms)
    +        | Terminal::Verify(ms)
    +        | Terminal::NonZero(ms)
    +        | Terminal::ZeroNotEqual(ms) => plan_steps(&ms.node, assets),
    +        Terminal::DupIf(ms) => {
    +            let mut plan = plan_steps(&ms.node, assets)?;
    +            plan.template.push(TemplateItem::One);
    +            Some(plan)
    +        }
    +        Terminal::AndV(l, r) | Terminal::AndB(l, r) => {
    +            let lhs = plan_steps(&l.node, assets)?;
    +            let rhs = plan_steps(&r.node, assets)?;
    +            lhs.combine(rhs)
    +        }
    +        Terminal::AndOr(_, _, _) => todo!(),
    +        Terminal::OrB(_, _) => todo!(),
    +        Terminal::OrD(_, _) => todo!(),
    +        Terminal::OrC(_, _) => todo!(),
    +        Terminal::OrI(lhs, rhs) => {
    +            let lplan = plan_steps(&lhs.node, assets).map(|mut plan| {
    +                plan.template.push(TemplateItem::One);
    +                plan
    +            });
    +            let rplan = plan_steps(&rhs.node, assets).map(|mut plan| {
    +                plan.template.push(TemplateItem::Zero);
    +                plan
    +            });
    +            match (lplan, rplan) {
    +                (Some(lplan), Some(rplan)) => {
    +                    if lplan.expected_size() <= rplan.expected_size() {
    +                        Some(lplan)
    +                    } else {
    +                        Some(rplan)
    +                    }
    +                }
    +                (lplan, rplan) => lplan.or(rplan),
    +            }
    +        }
    +        Terminal::Thresh(_, _) => todo!(),
    +        Terminal::Multi(_, _) => todo!(),
    +        Terminal::MultiA(_, _) => todo!(),
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/requirements.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/requirements.rs.html new file mode 100644 index 0000000000..73afceff07 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/requirements.rs.html @@ -0,0 +1,438 @@ +requirements.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +
    use bdk_chain::{bitcoin, collections::*, miniscript};
    +use core::ops::Deref;
    +
    +use bitcoin::{
    +    hashes::{hash160, ripemd160, sha256},
    +    psbt::Prevouts,
    +    secp256k1::{KeyPair, Message, PublicKey, Signing, Verification},
    +    util::{bip32, sighash, sighash::SighashCache, taproot},
    +    EcdsaSighashType, SchnorrSighashType, Transaction, TxOut, XOnlyPublicKey,
    +};
    +
    +use super::*;
    +use miniscript::{
    +    descriptor::{DescriptorSecretKey, KeyMap},
    +    hash256,
    +};
    +
    +#[derive(Clone, Debug)]
    +/// Signatures and hash pre-images that must be provided to complete the plan.
    +pub struct Requirements<Ak> {
    +    /// required signatures
    +    pub signatures: RequiredSignatures<Ak>,
    +    /// required sha256 pre-images
    +    pub sha256_images: HashSet<sha256::Hash>,
    +    /// required hash160 pre-images
    +    pub hash160_images: HashSet<hash160::Hash>,
    +    /// required hash256 pre-images
    +    pub hash256_images: HashSet<hash256::Hash>,
    +    /// required ripemd160 pre-images
    +    pub ripemd160_images: HashSet<ripemd160::Hash>,
    +}
    +
    +impl<Ak> Default for RequiredSignatures<Ak> {
    +    fn default() -> Self {
    +        RequiredSignatures::Legacy {
    +            keys: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<Ak> Default for Requirements<Ak> {
    +    fn default() -> Self {
    +        Self {
    +            signatures: Default::default(),
    +            sha256_images: Default::default(),
    +            hash160_images: Default::default(),
    +            hash256_images: Default::default(),
    +            ripemd160_images: Default::default(),
    +        }
    +    }
    +}
    +
    +impl<Ak> Requirements<Ak> {
    +    /// Whether any hash pre-images are required in the plan
    +    pub fn requires_hash_preimages(&self) -> bool {
    +        !(self.sha256_images.is_empty()
    +            && self.hash160_images.is_empty()
    +            && self.hash256_images.is_empty()
    +            && self.ripemd160_images.is_empty())
    +    }
    +}
    +
    +/// The signatures required to complete the plan
    +#[derive(Clone, Debug)]
    +pub enum RequiredSignatures<Ak> {
    +    /// Legacy ECDSA signatures are required
    +    Legacy { keys: Vec<PlanKey<Ak>> },
    +    /// Segwitv0 ECDSA signatures are required
    +    Segwitv0 { keys: Vec<PlanKey<Ak>> },
    +    /// A Taproot key spend signature is required
    +    TapKey {
    +        /// the internal key
    +        plan_key: PlanKey<Ak>,
    +        /// The merkle root of the taproot output
    +        merkle_root: Option<TapBranchHash>,
    +    },
    +    /// Taproot script path signatures are required
    +    TapScript {
    +        /// The leaf hash of the script being used
    +        leaf_hash: TapLeafHash,
    +        /// The keys in the script that require signatures
    +        plan_keys: Vec<PlanKey<Ak>>,
    +    },
    +}
    +
    +#[derive(Clone, Debug)]
    +pub enum SigningError {
    +    SigHashError(sighash::Error),
    +    DerivationError(bip32::Error),
    +}
    +
    +impl From<sighash::Error> for SigningError {
    +    fn from(e: sighash::Error) -> Self {
    +        Self::SigHashError(e)
    +    }
    +}
    +
    +impl core::fmt::Display for SigningError {
    +    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
    +        match self {
    +            SigningError::SigHashError(e) => e.fmt(f),
    +            SigningError::DerivationError(e) => e.fmt(f),
    +        }
    +    }
    +}
    +
    +impl From<bip32::Error> for SigningError {
    +    fn from(e: bip32::Error) -> Self {
    +        Self::DerivationError(e)
    +    }
    +}
    +
    +#[cfg(feature = "std")]
    +impl std::error::Error for SigningError {}
    +
    +impl RequiredSignatures<DescriptorPublicKey> {
    +    pub fn sign_with_keymap<T: Deref<Target = Transaction>>(
    +        &self,
    +        input_index: usize,
    +        keymap: &KeyMap,
    +        prevouts: &Prevouts<'_, impl core::borrow::Borrow<TxOut>>,
    +        schnorr_sighashty: Option<SchnorrSighashType>,
    +        _ecdsa_sighashty: Option<EcdsaSighashType>,
    +        sighash_cache: &mut SighashCache<T>,
    +        auth_data: &mut SatisfactionMaterial,
    +        secp: &Secp256k1<impl Signing + Verification>,
    +    ) -> Result<bool, SigningError> {
    +        match self {
    +            RequiredSignatures::Legacy { .. } | RequiredSignatures::Segwitv0 { .. } => todo!(),
    +            RequiredSignatures::TapKey {
    +                plan_key,
    +                merkle_root,
    +            } => {
    +                let schnorr_sighashty = schnorr_sighashty.unwrap_or(SchnorrSighashType::Default);
    +                let sighash = sighash_cache.taproot_key_spend_signature_hash(
    +                    input_index,
    +                    prevouts,
    +                    schnorr_sighashty,
    +                )?;
    +                let secret_key = match keymap.get(&plan_key.asset_key) {
    +                    Some(secret_key) => secret_key,
    +                    None => return Ok(false),
    +                };
    +                let secret_key = match secret_key {
    +                    DescriptorSecretKey::Single(single) => single.key.inner,
    +                    DescriptorSecretKey::XPrv(xprv) => {
    +                        xprv.xkey
    +                            .derive_priv(&secp, &plan_key.derivation_hint)?
    +                            .private_key
    +                    }
    +                };
    +
    +                let pubkey = PublicKey::from_secret_key(&secp, &secret_key);
    +                let x_only_pubkey = XOnlyPublicKey::from(pubkey);
    +
    +                let tweak =
    +                    taproot::TapTweakHash::from_key_and_tweak(x_only_pubkey, merkle_root.clone());
    +                let keypair = KeyPair::from_secret_key(&secp, &secret_key.clone())
    +                    .add_xonly_tweak(&secp, &tweak.to_scalar())
    +                    .unwrap();
    +
    +                let msg = Message::from_slice(sighash.as_ref()).expect("Sighashes are 32 bytes");
    +                let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair);
    +
    +                let bitcoin_sig = SchnorrSig {
    +                    sig,
    +                    hash_ty: schnorr_sighashty,
    +                };
    +
    +                auth_data
    +                    .schnorr_sigs
    +                    .insert(plan_key.descriptor_key.clone(), bitcoin_sig);
    +                Ok(true)
    +            }
    +            RequiredSignatures::TapScript {
    +                leaf_hash,
    +                plan_keys,
    +            } => {
    +                let sighash_type = schnorr_sighashty.unwrap_or(SchnorrSighashType::Default);
    +                let sighash = sighash_cache.taproot_script_spend_signature_hash(
    +                    input_index,
    +                    prevouts,
    +                    *leaf_hash,
    +                    sighash_type,
    +                )?;
    +
    +                let mut modified = false;
    +
    +                for plan_key in plan_keys {
    +                    if let Some(secret_key) = keymap.get(&plan_key.asset_key) {
    +                        let secret_key = match secret_key {
    +                            DescriptorSecretKey::Single(single) => single.key.inner,
    +                            DescriptorSecretKey::XPrv(xprv) => {
    +                                xprv.xkey
    +                                    .derive_priv(&secp, &plan_key.derivation_hint)?
    +                                    .private_key
    +                            }
    +                        };
    +                        let keypair = KeyPair::from_secret_key(&secp, &secret_key.clone());
    +                        let msg =
    +                            Message::from_slice(sighash.as_ref()).expect("Sighashes are 32 bytes");
    +                        let sig = secp.sign_schnorr_no_aux_rand(&msg, &keypair);
    +                        let bitcoin_sig = SchnorrSig {
    +                            sig,
    +                            hash_ty: sighash_type,
    +                        };
    +
    +                        auth_data
    +                            .schnorr_sigs
    +                            .insert(plan_key.descriptor_key.clone(), bitcoin_sig);
    +                        modified = true;
    +                    }
    +                }
    +                Ok(modified)
    +            }
    +        }
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/template.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/template.rs.html new file mode 100644 index 0000000000..0fca27af5a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_tmp_plan/template.rs.html @@ -0,0 +1,154 @@ +template.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +
    use bdk_chain::{bitcoin, miniscript};
    +use bitcoin::{
    +    hashes::{hash160, ripemd160, sha256},
    +    util::bip32::DerivationPath,
    +};
    +
    +use super::*;
    +use crate::{hash256, varint_len, DefiniteDescriptorKey};
    +
    +#[derive(Clone, Debug)]
    +pub(crate) enum TemplateItem<Ak> {
    +    Sign(PlanKey<Ak>),
    +    Pk { key: DefiniteDescriptorKey },
    +    One,
    +    Zero,
    +    Sha256(sha256::Hash),
    +    Hash256(hash256::Hash),
    +    Ripemd160(ripemd160::Hash),
    +    Hash160(hash160::Hash),
    +}
    +
    +/// A plan key contains the asset key originally provided along with key in the descriptor it
    +/// purports to be able to derive for along with a "hint" on how to derive it.
    +#[derive(Clone, Debug)]
    +pub struct PlanKey<Ak> {
    +    /// The key the planner will sign with
    +    pub asset_key: Ak,
    +    /// A hint from how to get from the asset key to the concrete key we need to sign with.
    +    pub derivation_hint: DerivationPath,
    +    /// The key that was in the descriptor that we are satisfying with the signature from the asset
    +    /// key.
    +    pub descriptor_key: DefiniteDescriptorKey,
    +}
    +
    +impl<Ak> TemplateItem<Ak> {
    +    pub fn expected_size(&self) -> usize {
    +        match self {
    +            TemplateItem::Sign { .. } => 64, /* size of sig TODO: take into consideration sighash falg */
    +            TemplateItem::Pk { .. } => 32,
    +            TemplateItem::One => varint_len(1),
    +            TemplateItem::Zero => 0, /* zero means an empty witness element */
    +            // I'm not sure if it should be 32 here (it's a 20 byte hash) but that's what other
    +            // parts of the code were doing.
    +            TemplateItem::Hash160(_) | TemplateItem::Ripemd160(_) => 32,
    +            TemplateItem::Sha256(_) | TemplateItem::Hash256(_) => 32,
    +        }
    +    }
    +
    +    // this can only be called if we are sure that auth_data has what we need
    +    pub(super) fn to_witness_stack(&self, auth_data: &SatisfactionMaterial) -> Vec<Vec<u8>> {
    +        match self {
    +            TemplateItem::Sign(plan_key) => {
    +                vec![auth_data
    +                    .schnorr_sigs
    +                    .get(&plan_key.descriptor_key)
    +                    .unwrap()
    +                    .to_vec()]
    +            }
    +            TemplateItem::One => vec![vec![1]],
    +            TemplateItem::Zero => vec![vec![]],
    +            TemplateItem::Sha256(image) => {
    +                vec![auth_data.sha256_preimages.get(image).unwrap().to_vec()]
    +            }
    +            TemplateItem::Hash160(image) => {
    +                vec![auth_data.hash160_preimages.get(image).unwrap().to_vec()]
    +            }
    +            TemplateItem::Ripemd160(image) => {
    +                vec![auth_data.ripemd160_preimages.get(image).unwrap().to_vec()]
    +            }
    +            TemplateItem::Hash256(image) => {
    +                vec![auth_data.hash256_preimages.get(image).unwrap().to_vec()]
    +            }
    +            TemplateItem::Pk { key } => vec![key.to_public_key().to_bytes()],
    +        }
    +    }
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_electrum_example/main.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_electrum_example/main.rs.html new file mode 100644 index 0000000000..1119bfca1b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_electrum_example/main.rs.html @@ -0,0 +1,492 @@ +main.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +
    use bdk_chain::bitcoin::{Address, OutPoint, Txid};
    +use bdk_electrum::bdk_chain::{self, bitcoin::Network, TxHeight};
    +use bdk_electrum::{
    +    electrum_client::{self, ElectrumApi},
    +    ElectrumExt, ElectrumUpdate,
    +};
    +use keychain_tracker_example_cli::{
    +    self as cli,
    +    anyhow::{self, Context},
    +    clap::{self, Parser, Subcommand},
    +};
    +use std::{collections::BTreeMap, fmt::Debug, io, io::Write};
    +
    +#[derive(Subcommand, Debug, Clone)]
    +enum ElectrumCommands {
    +    /// Scans the addresses in the wallet using esplora API.
    +    Scan {
    +        /// When a gap this large has been found for a keychain it will stop.
    +        #[clap(long, default_value = "5")]
    +        stop_gap: usize,
    +        #[clap(flatten)]
    +        scan_options: ScanOptions,
    +    },
    +    /// Scans particular addresses using esplora API
    +    Sync {
    +        /// Scan all the unused addresses
    +        #[clap(long)]
    +        unused_spks: bool,
    +        /// Scan every address that you have derived
    +        #[clap(long)]
    +        all_spks: bool,
    +        /// Scan unspent outpoints for spends or changes to confirmation status of residing tx
    +        #[clap(long)]
    +        utxos: bool,
    +        /// Scan unconfirmed transactions for updates
    +        #[clap(long)]
    +        unconfirmed: bool,
    +        #[clap(flatten)]
    +        scan_options: ScanOptions,
    +    },
    +}
    +
    +#[derive(Parser, Debug, Clone, PartialEq)]
    +pub struct ScanOptions {
    +    /// Set batch size for each script_history call to electrum client
    +    #[clap(long, default_value = "25")]
    +    pub batch_size: usize,
    +}
    +
    +fn main() -> anyhow::Result<()> {
    +    let (args, keymap, tracker, db) = cli::init::<ElectrumCommands, _>()?;
    +
    +    let electrum_url = match args.network {
    +        Network::Bitcoin => "ssl://electrum.blockstream.info:50002",
    +        Network::Testnet => "ssl://electrum.blockstream.info:60002",
    +        Network::Regtest => "tcp://localhost:60401",
    +        Network::Signet => "tcp://signet-electrumx.wakiyamap.dev:50001",
    +    };
    +    let config = electrum_client::Config::builder()
    +        .validate_domain(matches!(args.network, Network::Bitcoin))
    +        .build();
    +
    +    let client = electrum_client::Client::from_config(electrum_url, config)?;
    +
    +    let electrum_cmd = match args.command.clone() {
    +        cli::Commands::ChainSpecific(electrum_cmd) => electrum_cmd,
    +        general_command => {
    +            return cli::handle_commands(
    +                general_command,
    +                |transaction| {
    +                    let _txid = client.transaction_broadcast(transaction)?;
    +                    Ok(())
    +                },
    +                &tracker,
    +                &db,
    +                args.network,
    +                &keymap,
    +            )
    +        }
    +    };
    +
    +    let response = match electrum_cmd {
    +        ElectrumCommands::Scan {
    +            stop_gap,
    +            scan_options: scan_option,
    +        } => {
    +            let (spk_iterators, local_chain) = {
    +                // Get a short lock on the tracker to get the spks iterators
    +                // and local chain state
    +                let tracker = &*tracker.lock().unwrap();
    +                let spk_iterators = tracker
    +                    .txout_index
    +                    .spks_of_all_keychains()
    +                    .into_iter()
    +                    .map(|(keychain, iter)| {
    +                        let mut first = true;
    +                        let spk_iter = iter.inspect(move |(i, _)| {
    +                            if first {
    +                                eprint!("\nscanning {}: ", keychain);
    +                                first = false;
    +                            }
    +
    +                            eprint!("{} ", i);
    +                            let _ = io::stdout().flush();
    +                        });
    +                        (keychain, spk_iter)
    +                    })
    +                    .collect::<BTreeMap<_, _>>();
    +                let local_chain = tracker.chain().checkpoints().clone();
    +                (spk_iterators, local_chain)
    +            };
    +
    +            // we scan the spks **without** a lock on the tracker
    +            client.scan(
    +                &local_chain,
    +                spk_iterators,
    +                core::iter::empty(),
    +                core::iter::empty(),
    +                stop_gap,
    +                scan_option.batch_size,
    +            )?
    +        }
    +        ElectrumCommands::Sync {
    +            mut unused_spks,
    +            mut utxos,
    +            mut unconfirmed,
    +            all_spks,
    +            scan_options,
    +        } => {
    +            // Get a short lock on the tracker to get the spks we're interested in
    +            let tracker = tracker.lock().unwrap();
    +
    +            if !(all_spks || unused_spks || utxos || unconfirmed) {
    +                unused_spks = true;
    +                unconfirmed = true;
    +                utxos = true;
    +            } else if all_spks {
    +                unused_spks = false;
    +            }
    +
    +            let mut spks: Box<dyn Iterator<Item = bdk_chain::bitcoin::Script>> =
    +                Box::new(core::iter::empty());
    +            if all_spks {
    +                let all_spks = tracker
    +                    .txout_index
    +                    .all_spks()
    +                    .iter()
    +                    .map(|(k, v)| (*k, v.clone()))
    +                    .collect::<Vec<_>>();
    +                spks = Box::new(spks.chain(all_spks.into_iter().map(|(index, script)| {
    +                    eprintln!("scanning {:?}", index);
    +                    script
    +                })));
    +            }
    +            if unused_spks {
    +                let unused_spks = tracker
    +                    .txout_index
    +                    .unused_spks(..)
    +                    .map(|(k, v)| (*k, v.clone()))
    +                    .collect::<Vec<_>>();
    +                spks = Box::new(spks.chain(unused_spks.into_iter().map(|(index, script)| {
    +                    eprintln!(
    +                        "Checking if address {} {:?} has been used",
    +                        Address::from_script(&script, args.network).unwrap(),
    +                        index
    +                    );
    +
    +                    script
    +                })));
    +            }
    +
    +            let mut outpoints: Box<dyn Iterator<Item = OutPoint>> = Box::new(core::iter::empty());
    +
    +            if utxos {
    +                let utxos = tracker
    +                    .full_utxos()
    +                    .map(|(_, utxo)| utxo)
    +                    .collect::<Vec<_>>();
    +                outpoints = Box::new(
    +                    utxos
    +                        .into_iter()
    +                        .inspect(|utxo| {
    +                            eprintln!(
    +                                "Checking if outpoint {} (value: {}) has been spent",
    +                                utxo.outpoint, utxo.txout.value
    +                            );
    +                        })
    +                        .map(|utxo| utxo.outpoint),
    +                );
    +            };
    +
    +            let mut txids: Box<dyn Iterator<Item = Txid>> = Box::new(core::iter::empty());
    +
    +            if unconfirmed {
    +                let unconfirmed_txids = tracker
    +                    .chain()
    +                    .range_txids_by_height(TxHeight::Unconfirmed..)
    +                    .map(|(_, txid)| *txid)
    +                    .collect::<Vec<_>>();
    +
    +                txids = Box::new(unconfirmed_txids.into_iter().inspect(|txid| {
    +                    eprintln!("Checking if {} is confirmed yet", txid);
    +                }));
    +            }
    +
    +            let local_chain = tracker.chain().checkpoints().clone();
    +            // drop lock on tracker
    +            drop(tracker);
    +
    +            // we scan the spks **without** a lock on the tracker
    +            ElectrumUpdate {
    +                chain_update: client
    +                    .scan_without_keychain(
    +                        &local_chain,
    +                        spks,
    +                        txids,
    +                        outpoints,
    +                        scan_options.batch_size,
    +                    )
    +                    .context("scanning the blockchain")?,
    +                ..Default::default()
    +            }
    +        }
    +    };
    +
    +    let missing_txids = response.missing_full_txs(&*tracker.lock().unwrap());
    +
    +    // fetch the missing full transactions **without** a lock on the tracker
    +    let new_txs = client
    +        .batch_transaction_get(missing_txids)
    +        .context("fetching full transactions")?;
    +
    +    {
    +        // Get a final short lock to apply the changes
    +        let mut tracker = tracker.lock().unwrap();
    +        let changeset = {
    +            let scan = response.into_keychain_scan(new_txs, &*tracker)?;
    +            tracker.determine_changeset(&scan)?
    +        };
    +        db.lock().unwrap().append_changeset(&changeset)?;
    +        tracker.apply_changeset(changeset);
    +    };
    +
    +    Ok(())
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_esplora_example/main.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_esplora_example/main.rs.html new file mode 100644 index 0000000000..f96b84d48e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_esplora_example/main.rs.html @@ -0,0 +1,484 @@ +main.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +
    use bdk_chain::bitcoin::{Address, OutPoint, Txid};
    +use bdk_chain::{bitcoin::Network, TxHeight};
    +use bdk_esplora::esplora_client;
    +use bdk_esplora::EsploraExt;
    +
    +use std::io::{self, Write};
    +
    +use keychain_tracker_example_cli::{
    +    self as cli,
    +    anyhow::{self, Context},
    +    clap::{self, Parser, Subcommand},
    +};
    +
    +#[derive(Subcommand, Debug, Clone)]
    +enum EsploraCommands {
    +    /// Scans the addresses in the wallet using esplora API.
    +    Scan {
    +        /// When a gap this large has been found for a keychain it will stop.
    +        #[clap(long, default_value = "5")]
    +        stop_gap: usize,
    +
    +        #[clap(flatten)]
    +        scan_options: ScanOptions,
    +    },
    +    /// Scans particular addresses using esplora API
    +    Sync {
    +        /// Scan all the unused addresses
    +        #[clap(long)]
    +        unused_spks: bool,
    +        /// Scan every address that you have derived
    +        #[clap(long)]
    +        all_spks: bool,
    +        /// Scan unspent outpoints for spends or changes to confirmation status of residing tx
    +        #[clap(long)]
    +        utxos: bool,
    +        /// Scan unconfirmed transactions for updates
    +        #[clap(long)]
    +        unconfirmed: bool,
    +
    +        #[clap(flatten)]
    +        scan_options: ScanOptions,
    +    },
    +}
    +
    +#[derive(Parser, Debug, Clone, PartialEq)]
    +pub struct ScanOptions {
    +    #[clap(long, default_value = "5")]
    +    pub parallel_requests: usize,
    +}
    +
    +fn main() -> anyhow::Result<()> {
    +    let (args, keymap, keychain_tracker, db) = cli::init::<EsploraCommands, _>()?;
    +    let esplora_url = match args.network {
    +        Network::Bitcoin => "https://mempool.space/api",
    +        Network::Testnet => "https://mempool.space/testnet/api",
    +        Network::Regtest => "http://localhost:3002",
    +        Network::Signet => "https://mempool.space/signet/api",
    +    };
    +
    +    let client = esplora_client::Builder::new(esplora_url).build_blocking()?;
    +
    +    let esplora_cmd = match args.command {
    +        cli::Commands::ChainSpecific(esplora_cmd) => esplora_cmd,
    +        general_command => {
    +            return cli::handle_commands(
    +                general_command,
    +                |transaction| Ok(client.broadcast(transaction)?),
    +                &keychain_tracker,
    +                &db,
    +                args.network,
    +                &keymap,
    +            )
    +        }
    +    };
    +
    +    match esplora_cmd {
    +        EsploraCommands::Scan {
    +            stop_gap,
    +            scan_options,
    +        } => {
    +            let (spk_iterators, local_chain) = {
    +                // Get a short lock on the tracker to get the spks iterators
    +                // and local chain state
    +                let tracker = &*keychain_tracker.lock().unwrap();
    +                let spk_iterators = tracker
    +                    .txout_index
    +                    .spks_of_all_keychains()
    +                    .into_iter()
    +                    .map(|(keychain, iter)| {
    +                        let mut first = true;
    +                        (
    +                            keychain,
    +                            iter.inspect(move |(i, _)| {
    +                                if first {
    +                                    eprint!("\nscanning {}: ", keychain);
    +                                    first = false;
    +                                }
    +
    +                                eprint!("{} ", i);
    +                                let _ = io::stdout().flush();
    +                            }),
    +                        )
    +                    })
    +                    .collect();
    +
    +                let local_chain = tracker.chain().checkpoints().clone();
    +                (spk_iterators, local_chain)
    +            };
    +
    +            // we scan the iterators **without** a lock on the tracker
    +            let wallet_scan = client
    +                .scan(
    +                    &local_chain,
    +                    spk_iterators,
    +                    core::iter::empty(),
    +                    core::iter::empty(),
    +                    stop_gap,
    +                    scan_options.parallel_requests,
    +                )
    +                .context("scanning the blockchain")?;
    +            eprintln!();
    +
    +            {
    +                // we take a short lock to apply results to tracker and db
    +                let tracker = &mut *keychain_tracker.lock().unwrap();
    +                let db = &mut *db.lock().unwrap();
    +                let changeset = tracker.apply_update(wallet_scan)?;
    +                db.append_changeset(&changeset)?;
    +            }
    +        }
    +        EsploraCommands::Sync {
    +            mut unused_spks,
    +            mut utxos,
    +            mut unconfirmed,
    +            all_spks,
    +            scan_options,
    +        } => {
    +            // Get a short lock on the tracker to get the spks we're interested in
    +            let tracker = keychain_tracker.lock().unwrap();
    +
    +            if !(all_spks || unused_spks || utxos || unconfirmed) {
    +                unused_spks = true;
    +                unconfirmed = true;
    +                utxos = true;
    +            } else if all_spks {
    +                unused_spks = false;
    +            }
    +
    +            let mut spks: Box<dyn Iterator<Item = bdk_chain::bitcoin::Script>> =
    +                Box::new(core::iter::empty());
    +            if all_spks {
    +                let all_spks = tracker
    +                    .txout_index
    +                    .all_spks()
    +                    .iter()
    +                    .map(|(k, v)| (*k, v.clone()))
    +                    .collect::<Vec<_>>();
    +                spks = Box::new(spks.chain(all_spks.into_iter().map(|(index, script)| {
    +                    eprintln!("scanning {:?}", index);
    +                    script
    +                })));
    +            }
    +            if unused_spks {
    +                let unused_spks = tracker
    +                    .txout_index
    +                    .unused_spks(..)
    +                    .map(|(k, v)| (*k, v.clone()))
    +                    .collect::<Vec<_>>();
    +                spks = Box::new(spks.chain(unused_spks.into_iter().map(|(index, script)| {
    +                    eprintln!(
    +                        "Checking if address {} {:?} has been used",
    +                        Address::from_script(&script, args.network).unwrap(),
    +                        index
    +                    );
    +
    +                    script
    +                })));
    +            }
    +
    +            let mut outpoints: Box<dyn Iterator<Item = OutPoint>> = Box::new(core::iter::empty());
    +
    +            if utxos {
    +                let utxos = tracker
    +                    .full_utxos()
    +                    .map(|(_, utxo)| utxo)
    +                    .collect::<Vec<_>>();
    +                outpoints = Box::new(
    +                    utxos
    +                        .into_iter()
    +                        .inspect(|utxo| {
    +                            eprintln!(
    +                                "Checking if outpoint {} (value: {}) has been spent",
    +                                utxo.outpoint, utxo.txout.value
    +                            );
    +                        })
    +                        .map(|utxo| utxo.outpoint),
    +                );
    +            };
    +
    +            let mut txids: Box<dyn Iterator<Item = Txid>> = Box::new(core::iter::empty());
    +
    +            if unconfirmed {
    +                let unconfirmed_txids = tracker
    +                    .chain()
    +                    .range_txids_by_height(TxHeight::Unconfirmed..)
    +                    .map(|(_, txid)| *txid)
    +                    .collect::<Vec<_>>();
    +
    +                txids = Box::new(unconfirmed_txids.into_iter().inspect(|txid| {
    +                    eprintln!("Checking if {} is confirmed yet", txid);
    +                }));
    +            }
    +
    +            let local_chain = tracker.chain().checkpoints().clone();
    +
    +            // drop lock on tracker
    +            drop(tracker);
    +
    +            // we scan the desired spks **without** a lock on the tracker
    +            let scan = client
    +                .scan_without_keychain(
    +                    &local_chain,
    +                    spks,
    +                    txids,
    +                    outpoints,
    +                    scan_options.parallel_requests,
    +                )
    +                .context("scanning the blockchain")?;
    +
    +            {
    +                // we take a short lock to apply the results to the tracker and db
    +                let tracker = &mut *keychain_tracker.lock().unwrap();
    +                let changeset = tracker.apply_update(scan.into())?;
    +                let db = &mut *db.lock().unwrap();
    +                db.append_changeset(&changeset)?;
    +            }
    +        }
    +    }
    +
    +    Ok(())
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_example_cli/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_example_cli/lib.rs.html new file mode 100644 index 0000000000..5dd9021c2c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/keychain_tracker_example_cli/lib.rs.html @@ -0,0 +1,1386 @@ +lib.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
    +172
    +173
    +174
    +175
    +176
    +177
    +178
    +179
    +180
    +181
    +182
    +183
    +184
    +185
    +186
    +187
    +188
    +189
    +190
    +191
    +192
    +193
    +194
    +195
    +196
    +197
    +198
    +199
    +200
    +201
    +202
    +203
    +204
    +205
    +206
    +207
    +208
    +209
    +210
    +211
    +212
    +213
    +214
    +215
    +216
    +217
    +218
    +219
    +220
    +221
    +222
    +223
    +224
    +225
    +226
    +227
    +228
    +229
    +230
    +231
    +232
    +233
    +234
    +235
    +236
    +237
    +238
    +239
    +240
    +241
    +242
    +243
    +244
    +245
    +246
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +333
    +334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
    +449
    +450
    +451
    +452
    +453
    +454
    +455
    +456
    +457
    +458
    +459
    +460
    +461
    +462
    +463
    +464
    +465
    +466
    +467
    +468
    +469
    +470
    +471
    +472
    +473
    +474
    +475
    +476
    +477
    +478
    +479
    +480
    +481
    +482
    +483
    +484
    +485
    +486
    +487
    +488
    +489
    +490
    +491
    +492
    +493
    +494
    +495
    +496
    +497
    +498
    +499
    +500
    +501
    +502
    +503
    +504
    +505
    +506
    +507
    +508
    +509
    +510
    +511
    +512
    +513
    +514
    +515
    +516
    +517
    +518
    +519
    +520
    +521
    +522
    +523
    +524
    +525
    +526
    +527
    +528
    +529
    +530
    +531
    +532
    +533
    +534
    +535
    +536
    +537
    +538
    +539
    +540
    +541
    +542
    +543
    +544
    +545
    +546
    +547
    +548
    +549
    +550
    +551
    +552
    +553
    +554
    +555
    +556
    +557
    +558
    +559
    +560
    +561
    +562
    +563
    +564
    +565
    +566
    +567
    +568
    +569
    +570
    +571
    +572
    +573
    +574
    +575
    +576
    +577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +589
    +590
    +591
    +592
    +593
    +594
    +595
    +596
    +597
    +598
    +599
    +600
    +601
    +602
    +603
    +604
    +605
    +606
    +607
    +608
    +609
    +610
    +611
    +612
    +613
    +614
    +615
    +616
    +617
    +618
    +619
    +620
    +621
    +622
    +623
    +624
    +625
    +626
    +627
    +628
    +629
    +630
    +631
    +632
    +633
    +634
    +635
    +636
    +637
    +638
    +639
    +640
    +641
    +642
    +643
    +644
    +645
    +646
    +647
    +648
    +649
    +650
    +651
    +652
    +653
    +654
    +655
    +656
    +657
    +658
    +659
    +660
    +661
    +662
    +663
    +664
    +665
    +666
    +667
    +668
    +669
    +670
    +671
    +672
    +673
    +674
    +675
    +676
    +677
    +678
    +679
    +680
    +681
    +682
    +683
    +684
    +685
    +686
    +687
    +688
    +689
    +690
    +691
    +692
    +
    pub extern crate anyhow;
    +use anyhow::{anyhow, Context, Result};
    +use bdk_chain::{
    +    bitcoin::{
    +        secp256k1::Secp256k1,
    +        util::sighash::{Prevouts, SighashCache},
    +        Address, LockTime, Network, Sequence, Transaction, TxIn, TxOut,
    +    },
    +    chain_graph::InsertTxError,
    +    keychain::{DerivationAdditions, KeychainChangeSet, KeychainTracker},
    +    miniscript::{
    +        descriptor::{DescriptorSecretKey, KeyMap},
    +        Descriptor, DescriptorPublicKey,
    +    },
    +    sparse_chain::{self, ChainPosition},
    +    DescriptorExt, FullTxOut,
    +};
    +use bdk_coin_select::{coin_select_bnb, CoinSelector, CoinSelectorOpt, WeightedValue};
    +use bdk_file_store::KeychainStore;
    +use clap::{Parser, Subcommand};
    +use std::{
    +    cmp::Reverse, collections::HashMap, fmt::Debug, path::PathBuf, sync::Mutex, time::Duration,
    +};
    +
    +pub use bdk_file_store;
    +pub use clap;
    +
    +#[derive(Parser)]
    +#[clap(author, version, about, long_about = None)]
    +#[clap(propagate_version = true)]
    +pub struct Args<C: clap::Subcommand> {
    +    #[clap(env = "DESCRIPTOR")]
    +    pub descriptor: String,
    +    #[clap(env = "CHANGE_DESCRIPTOR")]
    +    pub change_descriptor: Option<String>,
    +
    +    #[clap(env = "BITCOIN_NETWORK", long, default_value = "signet")]
    +    pub network: Network,
    +
    +    #[clap(env = "BDK_DB_PATH", long, default_value = ".bdk_example_db")]
    +    pub db_path: PathBuf,
    +
    +    #[clap(env = "BDK_CP_LIMIT", long, default_value = "20")]
    +    pub cp_limit: usize,
    +
    +    #[clap(subcommand)]
    +    pub command: Commands<C>,
    +}
    +
    +#[derive(Subcommand, Debug, Clone)]
    +pub enum Commands<C: clap::Subcommand> {
    +    #[clap(flatten)]
    +    ChainSpecific(C),
    +    /// Address generation and inspection
    +    Address {
    +        #[clap(subcommand)]
    +        addr_cmd: AddressCmd,
    +    },
    +    /// Get the wallet balance
    +    Balance,
    +    /// TxOut related commands
    +    #[clap(name = "txout")]
    +    TxOut {
    +        #[clap(subcommand)]
    +        txout_cmd: TxOutCmd,
    +    },
    +    /// Send coins to an address
    +    Send {
    +        value: u64,
    +        address: Address,
    +        #[clap(short, default_value = "largest-first")]
    +        coin_select: CoinSelectionAlgo,
    +    },
    +}
    +
    +#[derive(Clone, Debug)]
    +pub enum CoinSelectionAlgo {
    +    LargestFirst,
    +    SmallestFirst,
    +    OldestFirst,
    +    NewestFirst,
    +    BranchAndBound,
    +}
    +
    +impl Default for CoinSelectionAlgo {
    +    fn default() -> Self {
    +        Self::LargestFirst
    +    }
    +}
    +
    +impl core::str::FromStr for CoinSelectionAlgo {
    +    type Err = anyhow::Error;
    +
    +    fn from_str(s: &str) -> Result<Self, Self::Err> {
    +        use CoinSelectionAlgo::*;
    +        Ok(match s {
    +            "largest-first" => LargestFirst,
    +            "smallest-first" => SmallestFirst,
    +            "oldest-first" => OldestFirst,
    +            "newest-first" => NewestFirst,
    +            "bnb" => BranchAndBound,
    +            unknown => return Err(anyhow!("unknown coin selection algorithm '{}'", unknown)),
    +        })
    +    }
    +}
    +
    +impl core::fmt::Display for CoinSelectionAlgo {
    +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    +        use CoinSelectionAlgo::*;
    +        write!(
    +            f,
    +            "{}",
    +            match self {
    +                LargestFirst => "largest-first",
    +                SmallestFirst => "smallest-first",
    +                OldestFirst => "oldest-first",
    +                NewestFirst => "newest-first",
    +                BranchAndBound => "bnb",
    +            }
    +        )
    +    }
    +}
    +
    +#[derive(Subcommand, Debug, Clone)]
    +pub enum AddressCmd {
    +    /// Get the next unused address
    +    Next,
    +    /// Get a new address regardless if the existing ones haven't been used
    +    New,
    +    /// List all addresses
    +    List {
    +        #[clap(long)]
    +        change: bool,
    +    },
    +    Index,
    +}
    +
    +#[derive(Subcommand, Debug, Clone)]
    +pub enum TxOutCmd {
    +    List {
    +        /// Return only spent outputs
    +        #[clap(short, long)]
    +        spent: bool,
    +        /// Return only unspent outputs
    +        #[clap(short, long)]
    +        unspent: bool,
    +        /// Return only confirmed outputs
    +        #[clap(long)]
    +        confirmed: bool,
    +        /// Return only unconfirmed outputs
    +        #[clap(long)]
    +        unconfirmed: bool,
    +    },
    +}
    +
    +#[derive(
    +    Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, serde::Deserialize, serde::Serialize,
    +)]
    +pub enum Keychain {
    +    External,
    +    Internal,
    +}
    +
    +impl core::fmt::Display for Keychain {
    +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    +        match self {
    +            Keychain::External => write!(f, "external"),
    +            Keychain::Internal => write!(f, "internal"),
    +        }
    +    }
    +}
    +
    +/// A structure defining output of a AddressCmd execution.
    +#[derive(serde::Serialize, serde::Deserialize)]
    +pub struct AddrsOutput {
    +    keychain: String,
    +    index: u32,
    +    addrs: Address,
    +    used: bool,
    +}
    +
    +pub fn run_address_cmd<P>(
    +    tracker: &Mutex<KeychainTracker<Keychain, P>>,
    +    db: &Mutex<KeychainStore<Keychain, P>>,
    +    addr_cmd: AddressCmd,
    +    network: Network,
    +) -> Result<()>
    +where
    +    P: bdk_chain::sparse_chain::ChainPosition,
    +    KeychainChangeSet<Keychain, P>: serde::Serialize + serde::de::DeserializeOwned,
    +{
    +    let mut tracker = tracker.lock().unwrap();
    +    let txout_index = &mut tracker.txout_index;
    +
    +    let addr_cmmd_output = match addr_cmd {
    +        AddressCmd::Next => Some(txout_index.next_unused_spk(&Keychain::External)),
    +        AddressCmd::New => Some(txout_index.reveal_next_spk(&Keychain::External)),
    +        _ => None,
    +    };
    +
    +    if let Some(((index, spk), additions)) = addr_cmmd_output {
    +        let mut db = db.lock().unwrap();
    +        // update database since we're about to give out a new address
    +        db.append_changeset(&additions.into())?;
    +
    +        let spk = spk.clone();
    +        let address =
    +            Address::from_script(&spk, network).expect("should always be able to derive address");
    +        eprintln!("This is the address at index {}", index);
    +        println!("{}", address);
    +    }
    +
    +    match addr_cmd {
    +        AddressCmd::Next | AddressCmd::New => {
    +            /* covered */
    +            Ok(())
    +        }
    +        AddressCmd::Index => {
    +            for (keychain, derivation_index) in txout_index.last_revealed_indices() {
    +                println!("{:?}: {}", keychain, derivation_index);
    +            }
    +            Ok(())
    +        }
    +        AddressCmd::List { change } => {
    +            let target_keychain = match change {
    +                true => Keychain::Internal,
    +                false => Keychain::External,
    +            };
    +            for (index, spk) in txout_index.revealed_spks_of_keychain(&target_keychain) {
    +                let address = Address::from_script(spk, network)
    +                    .expect("should always be able to derive address");
    +                println!(
    +                    "{:?} {} used:{}",
    +                    index,
    +                    address,
    +                    txout_index.is_used(&(target_keychain, index))
    +                );
    +            }
    +            Ok(())
    +        }
    +    }
    +}
    +
    +pub fn run_balance_cmd<P: ChainPosition>(tracker: &Mutex<KeychainTracker<Keychain, P>>) {
    +    let tracker = tracker.lock().unwrap();
    +    let (confirmed, unconfirmed) =
    +        tracker
    +            .full_utxos()
    +            .fold((0, 0), |(confirmed, unconfirmed), (_, utxo)| {
    +                if utxo.chain_position.height().is_confirmed() {
    +                    (confirmed + utxo.txout.value, unconfirmed)
    +                } else {
    +                    (confirmed, unconfirmed + utxo.txout.value)
    +                }
    +            });
    +
    +    println!("confirmed: {}", confirmed);
    +    println!("unconfirmed: {}", unconfirmed);
    +}
    +
    +pub fn run_txo_cmd<K: Debug + Clone + Ord, P: ChainPosition>(
    +    txout_cmd: TxOutCmd,
    +    tracker: &Mutex<KeychainTracker<K, P>>,
    +    network: Network,
    +) {
    +    match txout_cmd {
    +        TxOutCmd::List {
    +            unspent,
    +            spent,
    +            confirmed,
    +            unconfirmed,
    +        } => {
    +            let tracker = tracker.lock().unwrap();
    +            #[allow(clippy::type_complexity)] // FIXME
    +            let txouts: Box<dyn Iterator<Item = (&(K, u32), FullTxOut<P>)>> = match (unspent, spent)
    +            {
    +                (true, false) => Box::new(tracker.full_utxos()),
    +                (false, true) => Box::new(
    +                    tracker
    +                        .full_txouts()
    +                        .filter(|(_, txout)| txout.spent_by.is_some()),
    +                ),
    +                _ => Box::new(tracker.full_txouts()),
    +            };
    +
    +            #[allow(clippy::type_complexity)] // FIXME
    +            let txouts: Box<dyn Iterator<Item = (&(K, u32), FullTxOut<P>)>> =
    +                match (confirmed, unconfirmed) {
    +                    (true, false) => Box::new(
    +                        txouts.filter(|(_, txout)| txout.chain_position.height().is_confirmed()),
    +                    ),
    +                    (false, true) => Box::new(
    +                        txouts.filter(|(_, txout)| !txout.chain_position.height().is_confirmed()),
    +                    ),
    +                    _ => txouts,
    +                };
    +
    +            for (spk_index, full_txout) in txouts {
    +                let address =
    +                    Address::from_script(&full_txout.txout.script_pubkey, network).unwrap();
    +
    +                println!(
    +                    "{:?} {} {} {} spent:{:?}",
    +                    spk_index,
    +                    full_txout.txout.value,
    +                    full_txout.outpoint,
    +                    address,
    +                    full_txout.spent_by
    +                )
    +            }
    +        }
    +    }
    +}
    +
    +#[allow(clippy::type_complexity)] // FIXME
    +pub fn create_tx<P: ChainPosition>(
    +    value: u64,
    +    address: Address,
    +    coin_select: CoinSelectionAlgo,
    +    keychain_tracker: &mut KeychainTracker<Keychain, P>,
    +    keymap: &HashMap<DescriptorPublicKey, DescriptorSecretKey>,
    +) -> Result<(
    +    Transaction,
    +    Option<(DerivationAdditions<Keychain>, (Keychain, u32))>,
    +)> {
    +    let mut additions = DerivationAdditions::default();
    +
    +    let assets = bdk_tmp_plan::Assets {
    +        keys: keymap.iter().map(|(pk, _)| pk.clone()).collect(),
    +        ..Default::default()
    +    };
    +
    +    // TODO use planning module
    +    let mut candidates = planned_utxos(keychain_tracker, &assets).collect::<Vec<_>>();
    +
    +    // apply coin selection algorithm
    +    match coin_select {
    +        CoinSelectionAlgo::LargestFirst => {
    +            candidates.sort_by_key(|(_, utxo)| Reverse(utxo.txout.value))
    +        }
    +        CoinSelectionAlgo::SmallestFirst => candidates.sort_by_key(|(_, utxo)| utxo.txout.value),
    +        CoinSelectionAlgo::OldestFirst => {
    +            candidates.sort_by_key(|(_, utxo)| utxo.chain_position.clone())
    +        }
    +        CoinSelectionAlgo::NewestFirst => {
    +            candidates.sort_by_key(|(_, utxo)| Reverse(utxo.chain_position.clone()))
    +        }
    +        CoinSelectionAlgo::BranchAndBound => {}
    +    }
    +
    +    // turn the txos we chose into a weight and value
    +    let wv_candidates = candidates
    +        .iter()
    +        .map(|(plan, utxo)| {
    +            WeightedValue::new(
    +                utxo.txout.value,
    +                plan.expected_weight() as _,
    +                plan.witness_version().is_some(),
    +            )
    +        })
    +        .collect();
    +
    +    let mut outputs = vec![TxOut {
    +        value,
    +        script_pubkey: address.script_pubkey(),
    +    }];
    +
    +    let internal_keychain = if keychain_tracker
    +        .txout_index
    +        .keychains()
    +        .get(&Keychain::Internal)
    +        .is_some()
    +    {
    +        Keychain::Internal
    +    } else {
    +        Keychain::External
    +    };
    +
    +    let ((change_index, change_script), change_additions) = keychain_tracker
    +        .txout_index
    +        .next_unused_spk(&internal_keychain);
    +    additions.append(change_additions);
    +
    +    // Clone to drop the immutable reference.
    +    let change_script = change_script.clone();
    +
    +    let change_plan = bdk_tmp_plan::plan_satisfaction(
    +        &keychain_tracker
    +            .txout_index
    +            .keychains()
    +            .get(&internal_keychain)
    +            .expect("must exist")
    +            .at_derivation_index(change_index),
    +        &assets,
    +    )
    +    .expect("failed to obtain change plan");
    +
    +    let mut change_output = TxOut {
    +        value: 0,
    +        script_pubkey: change_script,
    +    };
    +
    +    let cs_opts = CoinSelectorOpt {
    +        target_feerate: 0.5,
    +        min_drain_value: keychain_tracker
    +            .txout_index
    +            .keychains()
    +            .get(&internal_keychain)
    +            .expect("must exist")
    +            .dust_value(),
    +        ..CoinSelectorOpt::fund_outputs(
    +            &outputs,
    +            &change_output,
    +            change_plan.expected_weight() as u32,
    +        )
    +    };
    +
    +    // TODO: How can we make it easy to shuffle in order of inputs and outputs here?
    +    // apply coin selection by saying we need to fund these outputs
    +    let mut coin_selector = CoinSelector::new(&wv_candidates, &cs_opts);
    +
    +    // just select coins in the order provided until we have enough
    +    // only use first result (least waste)
    +    let selection = match coin_select {
    +        CoinSelectionAlgo::BranchAndBound => {
    +            coin_select_bnb(Duration::from_secs(10), coin_selector.clone())
    +                .map_or_else(|| coin_selector.select_until_finished(), |cs| cs.finish())?
    +        }
    +        _ => coin_selector.select_until_finished()?,
    +    };
    +    let (_, selection_meta) = selection.best_strategy();
    +
    +    // get the selected utxos
    +    let selected_txos = selection.apply_selection(&candidates).collect::<Vec<_>>();
    +
    +    if let Some(drain_value) = selection_meta.drain_value {
    +        change_output.value = drain_value;
    +        // if the selection tells us to use change and the change value is sufficient we add it as an output
    +        outputs.push(change_output)
    +    }
    +
    +    let mut transaction = Transaction {
    +        version: 0x02,
    +        lock_time: keychain_tracker
    +            .chain()
    +            .latest_checkpoint()
    +            .and_then(|block_id| LockTime::from_height(block_id.height).ok())
    +            .unwrap_or(LockTime::ZERO)
    +            .into(),
    +        input: selected_txos
    +            .iter()
    +            .map(|(_, utxo)| TxIn {
    +                previous_output: utxo.outpoint,
    +                sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
    +                ..Default::default()
    +            })
    +            .collect(),
    +        output: outputs,
    +    };
    +
    +    let prevouts = selected_txos
    +        .iter()
    +        .map(|(_, utxo)| utxo.txout.clone())
    +        .collect::<Vec<_>>();
    +    let sighash_prevouts = Prevouts::All(&prevouts);
    +
    +    // first set tx values for plan so that we don't change them while signing
    +    for (i, (plan, _)) in selected_txos.iter().enumerate() {
    +        if let Some(sequence) = plan.required_sequence() {
    +            transaction.input[i].sequence = sequence
    +        }
    +    }
    +
    +    // create a short lived transaction
    +    let _sighash_tx = transaction.clone();
    +    let mut sighash_cache = SighashCache::new(&_sighash_tx);
    +
    +    for (i, (plan, _)) in selected_txos.iter().enumerate() {
    +        let requirements = plan.requirements();
    +        let mut auth_data = bdk_tmp_plan::SatisfactionMaterial::default();
    +        assert!(
    +            !requirements.requires_hash_preimages(),
    +            "can't have hash pre-images since we didn't provide any"
    +        );
    +        assert!(
    +            requirements.signatures.sign_with_keymap(
    +                i,
    +                keymap,
    +                &sighash_prevouts,
    +                None,
    +                None,
    +                &mut sighash_cache,
    +                &mut auth_data,
    +                &Secp256k1::default(),
    +            )?,
    +            "we should have signed with this input"
    +        );
    +
    +        match plan.try_complete(&auth_data) {
    +            bdk_tmp_plan::PlanState::Complete {
    +                final_script_sig,
    +                final_script_witness,
    +            } => {
    +                if let Some(witness) = final_script_witness {
    +                    transaction.input[i].witness = witness;
    +                }
    +
    +                if let Some(script_sig) = final_script_sig {
    +                    transaction.input[i].script_sig = script_sig;
    +                }
    +            }
    +            bdk_tmp_plan::PlanState::Incomplete(_) => {
    +                return Err(anyhow!(
    +                    "we weren't able to complete the plan with our keys"
    +                ));
    +            }
    +        }
    +    }
    +
    +    let change_info = if selection_meta.drain_value.is_some() {
    +        Some((additions, (internal_keychain, change_index)))
    +    } else {
    +        None
    +    };
    +
    +    Ok((transaction, change_info))
    +}
    +
    +pub fn handle_commands<C: clap::Subcommand, P>(
    +    command: Commands<C>,
    +    broadcast: impl FnOnce(&Transaction) -> Result<()>,
    +    // we Mutexes around these not because we need them for a simple CLI app but to demonsrate how
    +    // all the stuff we're doing can be thread safe and also not keep locks up over an IO bound.
    +    tracker: &Mutex<KeychainTracker<Keychain, P>>,
    +    store: &Mutex<KeychainStore<Keychain, P>>,
    +    network: Network,
    +    keymap: &HashMap<DescriptorPublicKey, DescriptorSecretKey>,
    +) -> Result<()>
    +where
    +    P: ChainPosition,
    +    KeychainChangeSet<Keychain, P>: serde::Serialize + serde::de::DeserializeOwned,
    +{
    +    match command {
    +        // TODO: Make these functions return stuffs
    +        Commands::Address { addr_cmd } => run_address_cmd(tracker, store, addr_cmd, network),
    +        Commands::Balance => {
    +            run_balance_cmd(tracker);
    +            Ok(())
    +        }
    +        Commands::TxOut { txout_cmd } => {
    +            run_txo_cmd(txout_cmd, tracker, network);
    +            Ok(())
    +        }
    +        Commands::Send {
    +            value,
    +            address,
    +            coin_select,
    +        } => {
    +            let (transaction, change_index) = {
    +                // take mutable ref to construct tx -- it is only open for a short time while building it.
    +                let tracker = &mut *tracker.lock().unwrap();
    +                let (transaction, change_info) =
    +                    create_tx(value, address, coin_select, tracker, keymap)?;
    +
    +                if let Some((change_derivation_changes, (change_keychain, index))) = change_info {
    +                    // We must first persist to disk the fact that we've got a new address from the
    +                    // change keychain so future scans will find the tx we're about to broadcast.
    +                    // If we're unable to persist this then we don't want to broadcast.
    +                    let store = &mut *store.lock().unwrap();
    +                    store.append_changeset(&change_derivation_changes.into())?;
    +
    +                    // We don't want other callers/threads to use this address while we're using it
    +                    // but we also don't want to scan the tx we just created because it's not
    +                    // technically in the blockchain yet.
    +                    tracker.txout_index.mark_used(&change_keychain, index);
    +                    (transaction, Some((change_keychain, index)))
    +                } else {
    +                    (transaction, None)
    +                }
    +            };
    +
    +            match (broadcast)(&transaction) {
    +                Ok(_) => {
    +                    println!("Broadcasted Tx : {}", transaction.txid());
    +                    let mut tracker = tracker.lock().unwrap();
    +                    match tracker.insert_tx(transaction.clone(), P::unconfirmed()) {
    +                        Ok(changeset) => {
    +                            let store = &mut *store.lock().unwrap();
    +                            // We know the tx is at least unconfirmed now. Note if persisting here
    +                            // fails it's not a big deal since we can always find it again form
    +                            // blockchain.
    +                            store.append_changeset(&changeset)?;
    +                            Ok(())
    +                        }
    +                        Err(e) => match e {
    +                            InsertTxError::Chain(e) => match e {
    +                                // TODO: add insert_unconfirmed_tx to chain graph and sparse chain
    +                                sparse_chain::InsertTxError::TxTooHigh { .. } => unreachable!("we are inserting at unconfirmed position"),
    +                                sparse_chain::InsertTxError::TxMovedUnexpectedly { txid, original_pos, ..} => Err(anyhow!("the tx we created {} has already been confirmed at block {:?}", txid, original_pos)),
    +                            },
    +                            InsertTxError::UnresolvableConflict(e) => Err(e).context("another tx that conflicts with the one we tried to create has been confirmed"),
    +                        }
    +                    }
    +                }
    +                Err(e) => {
    +                    let tracker = &mut *tracker.lock().unwrap();
    +                    if let Some((keychain, index)) = change_index {
    +                        // We failed to broadcast so allow our change address to be used in the future
    +                        tracker.txout_index.unmark_used(&keychain, index);
    +                    }
    +                    Err(e)
    +                }
    +            }
    +        }
    +        Commands::ChainSpecific(_) => {
    +            todo!("example code is meant to handle this!")
    +        }
    +    }
    +}
    +
    +#[allow(clippy::type_complexity)] // FIXME
    +pub fn init<C: clap::Subcommand, P>() -> anyhow::Result<(
    +    Args<C>,
    +    KeyMap,
    +    // These don't need to have mutexes around them but we want the cli example code to make it obvious how they
    +    // are thread safe so this forces the example developer to show where they would lock and unlock things.
    +    Mutex<KeychainTracker<Keychain, P>>,
    +    Mutex<KeychainStore<Keychain, P>>,
    +)>
    +where
    +    P: sparse_chain::ChainPosition,
    +    KeychainChangeSet<Keychain, P>: serde::Serialize + serde::de::DeserializeOwned,
    +{
    +    let args = Args::<C>::parse();
    +    let secp = Secp256k1::default();
    +    let (descriptor, mut keymap) =
    +        Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &args.descriptor)?;
    +
    +    let mut tracker = KeychainTracker::default();
    +    tracker.set_checkpoint_limit(Some(args.cp_limit));
    +
    +    tracker
    +        .txout_index
    +        .add_keychain(Keychain::External, descriptor);
    +
    +    let internal = args
    +        .change_descriptor
    +        .clone()
    +        .map(|descriptor| Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &descriptor))
    +        .transpose()?;
    +    if let Some((internal_descriptor, internal_keymap)) = internal {
    +        keymap.extend(internal_keymap);
    +        tracker
    +            .txout_index
    +            .add_keychain(Keychain::Internal, internal_descriptor);
    +    };
    +
    +    let mut db = KeychainStore::<Keychain, P>::new_from_path(args.db_path.as_path())?;
    +
    +    if let Err(e) = db.load_into_keychain_tracker(&mut tracker) {
    +        match tracker.chain().latest_checkpoint()  {
    +            Some(checkpoint) => eprintln!("Failed to load all changesets from {}. Last checkpoint was at height {}. Error: {}", args.db_path.display(), checkpoint.height, e),
    +            None => eprintln!("Failed to load any checkpoints from {}: {}", args.db_path.display(), e),
    +
    +        }
    +        eprintln!("⚠ Consider running a rescan of chain data.");
    +    }
    +
    +    Ok((args, keymap, Mutex::new(tracker), Mutex::new(db)))
    +}
    +
    +pub fn planned_utxos<'a, AK: bdk_tmp_plan::CanDerive + Clone, P: ChainPosition>(
    +    tracker: &'a KeychainTracker<Keychain, P>,
    +    assets: &'a bdk_tmp_plan::Assets<AK>,
    +) -> impl Iterator<Item = (bdk_tmp_plan::Plan<AK>, FullTxOut<P>)> + 'a {
    +    tracker
    +        .full_utxos()
    +        .filter_map(move |((keychain, derivation_index), full_txout)| {
    +            Some((
    +                bdk_tmp_plan::plan_satisfaction(
    +                    &tracker
    +                        .txout_index
    +                        .keychains()
    +                        .get(keychain)
    +                        .expect("must exist since we have a utxo for it")
    +                        .at_derivation_index(*derivation_index),
    +                    assets,
    +                )?,
    +                full_txout,
    +            ))
    +        })
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_electrum_example/main.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_electrum_example/main.rs.html new file mode 100644 index 0000000000..9c9d731559 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_electrum_example/main.rs.html @@ -0,0 +1,210 @@ +main.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +
    use std::{io::Write, str::FromStr};
    +
    +use bdk::{
    +    bitcoin::{Address, Network},
    +    SignOptions, Wallet,
    +};
    +use bdk_electrum::{
    +    electrum_client::{self, ElectrumApi},
    +    ElectrumExt,
    +};
    +use bdk_file_store::KeychainStore;
    +
    +const SEND_AMOUNT: u64 = 5000;
    +const STOP_GAP: usize = 50;
    +const BATCH_SIZE: usize = 5;
    +
    +fn main() -> Result<(), Box<dyn std::error::Error>> {
    +    println!("Hello, world!");
    +
    +    let db_path = std::env::temp_dir().join("bdk-electrum-example");
    +    let db = KeychainStore::new_from_path(db_path)?;
    +    let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)";
    +    let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)";
    +
    +    let mut wallet = Wallet::new(
    +        external_descriptor,
    +        Some(internal_descriptor),
    +        db,
    +        Network::Testnet,
    +    )?;
    +
    +    let address = wallet.get_address(bdk::wallet::AddressIndex::New);
    +    println!("Generated Address: {}", address);
    +
    +    let balance = wallet.get_balance();
    +    println!("Wallet balance before syncing: {} sats", balance.total());
    +
    +    print!("Syncing...");
    +    // Scanning the chain...
    +    let electrum_url = "ssl://electrum.blockstream.info:60002";
    +    let client = electrum_client::Client::new(electrum_url)?;
    +    let local_chain = wallet.checkpoints();
    +    let spks = wallet
    +        .spks_of_all_keychains()
    +        .into_iter()
    +        .map(|(k, spks)| {
    +            let mut first = true;
    +            (
    +                k,
    +                spks.inspect(move |(spk_i, _)| {
    +                    if first {
    +                        first = false;
    +                        print!("\nScanning keychain [{:?}]:", k);
    +                    }
    +                    print!(" {}", spk_i);
    +                    let _ = std::io::stdout().flush();
    +                }),
    +            )
    +        })
    +        .collect();
    +    let electrum_update = client
    +        .scan(
    +            local_chain,
    +            spks,
    +            core::iter::empty(),
    +            core::iter::empty(),
    +            STOP_GAP,
    +            BATCH_SIZE,
    +        )?
    +        .into_confirmation_time_update(&client)?;
    +    println!();
    +    let new_txs = client.batch_transaction_get(electrum_update.missing_full_txs(&wallet))?;
    +    let update = electrum_update.into_keychain_scan(new_txs, &wallet)?;
    +    wallet.apply_update(update)?;
    +    wallet.commit()?;
    +
    +    let balance = wallet.get_balance();
    +    println!("Wallet balance after syncing: {} sats", balance.total());
    +
    +    if balance.total() < SEND_AMOUNT {
    +        println!(
    +            "Please send at least {} sats to the receiving address",
    +            SEND_AMOUNT
    +        );
    +        std::process::exit(0);
    +    }
    +
    +    let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?;
    +
    +    let mut tx_builder = wallet.build_tx();
    +    tx_builder
    +        .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
    +        .enable_rbf();
    +
    +    let (mut psbt, _) = tx_builder.finish()?;
    +    let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    +    assert!(finalized);
    +
    +    let tx = psbt.extract_tx();
    +    client.transaction_broadcast(&tx)?;
    +    println!("Tx broadcasted! Txid: {}", tx.txid());
    +
    +    Ok(())
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_esplora_async/main.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_esplora_async/main.rs.html new file mode 100644 index 0000000000..38e9e5132b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_esplora_async/main.rs.html @@ -0,0 +1,200 @@ +main.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +
    use std::{io::Write, str::FromStr};
    +
    +use bdk::{
    +    bitcoin::{Address, Network},
    +    wallet::AddressIndex,
    +    SignOptions, Wallet,
    +};
    +use bdk_esplora::{esplora_client, EsploraAsyncExt};
    +use bdk_file_store::KeychainStore;
    +
    +const SEND_AMOUNT: u64 = 5000;
    +const STOP_GAP: usize = 50;
    +const PARALLEL_REQUESTS: usize = 5;
    +
    +#[tokio::main]
    +async fn main() -> Result<(), Box<dyn std::error::Error>> {
    +    let db_path = std::env::temp_dir().join("bdk-esplora-example");
    +    let db = KeychainStore::new_from_path(db_path)?;
    +    let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)";
    +    let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)";
    +
    +    let mut wallet = Wallet::new(
    +        external_descriptor,
    +        Some(internal_descriptor),
    +        db,
    +        Network::Testnet,
    +    )?;
    +
    +    let address = wallet.get_address(AddressIndex::New);
    +    println!("Generated Address: {}", address);
    +
    +    let balance = wallet.get_balance();
    +    println!("Wallet balance before syncing: {} sats", balance.total());
    +
    +    print!("Syncing...");
    +    // Scanning the blockchain
    +    let esplora_url = "https://mempool.space/testnet/api";
    +    let client = esplora_client::Builder::new(esplora_url).build_async()?;
    +    let checkpoints = wallet.checkpoints();
    +    let spks = wallet
    +        .spks_of_all_keychains()
    +        .into_iter()
    +        .map(|(k, spks)| {
    +            let mut first = true;
    +            (
    +                k,
    +                spks.inspect(move |(spk_i, _)| {
    +                    if first {
    +                        first = false;
    +                        print!("\nScanning keychain [{:?}]:", k);
    +                    }
    +                    print!(" {}", spk_i);
    +                    let _ = std::io::stdout().flush();
    +                }),
    +            )
    +        })
    +        .collect();
    +    let update = client
    +        .scan(
    +            checkpoints,
    +            spks,
    +            std::iter::empty(),
    +            std::iter::empty(),
    +            STOP_GAP,
    +            PARALLEL_REQUESTS,
    +        )
    +        .await?;
    +    println!();
    +    wallet.apply_update(update)?;
    +    wallet.commit()?;
    +
    +    let balance = wallet.get_balance();
    +    println!("Wallet balance after syncing: {} sats", balance.total());
    +
    +    if balance.total() < SEND_AMOUNT {
    +        println!(
    +            "Please send at least {} sats to the receiving address",
    +            SEND_AMOUNT
    +        );
    +        std::process::exit(0);
    +    }
    +
    +    let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?;
    +
    +    let mut tx_builder = wallet.build_tx();
    +    tx_builder
    +        .add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
    +        .enable_rbf();
    +
    +    let (mut psbt, _) = tx_builder.finish()?;
    +    let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    +    assert!(finalized);
    +
    +    let tx = psbt.extract_tx();
    +    client.broadcast(&tx).await?;
    +    println!("Tx broadcasted! Txid: {}", tx.txid());
    +
    +    Ok(())
    +}
    +
    +
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/all.html new file mode 100644 index 0000000000..4e9dd4930b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Functions

    Constants

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.BATCH_SIZE.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.BATCH_SIZE.html new file mode 100644 index 0000000000..7605952745 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.BATCH_SIZE.html @@ -0,0 +1 @@ +BATCH_SIZE in wallet_electrum_example - Rust
    pub(crate) const BATCH_SIZE: usize = 5;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.SEND_AMOUNT.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.SEND_AMOUNT.html new file mode 100644 index 0000000000..ca91b78769 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.SEND_AMOUNT.html @@ -0,0 +1 @@ +SEND_AMOUNT in wallet_electrum_example - Rust
    pub(crate) const SEND_AMOUNT: u64 = 5000;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.STOP_GAP.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.STOP_GAP.html new file mode 100644 index 0000000000..243cfd5525 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/constant.STOP_GAP.html @@ -0,0 +1 @@ +STOP_GAP in wallet_electrum_example - Rust
    pub(crate) const STOP_GAP: usize = 50;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/fn.main.html new file mode 100644 index 0000000000..14b2305115 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/fn.main.html @@ -0,0 +1 @@ +main in wallet_electrum_example - Rust

    Function wallet_electrum_example::main

    source ·
    pub(crate) fn main() -> Result<(), Box<dyn Error>>
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/index.html new file mode 100644 index 0000000000..3e4e162fad --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/index.html @@ -0,0 +1 @@ +wallet_electrum_example - Rust

    Constants

    BATCH_SIZE ðŸ”’
    SEND_AMOUNT ðŸ”’
    STOP_GAP ðŸ”’

    Functions

    main ðŸ”’
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/sidebar-items.js new file mode 100644 index 0000000000..d15c08356e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_electrum_example/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":[["BATCH_SIZE",""],["SEND_AMOUNT",""],["STOP_GAP",""]],"fn":[["main",""]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/all.html new file mode 100644 index 0000000000..ff45e31bb4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/all.html @@ -0,0 +1 @@ +List of all items in this crate

    List of all items

    Functions

    Constants

    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.PARALLEL_REQUESTS.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.PARALLEL_REQUESTS.html new file mode 100644 index 0000000000..67ef1a001d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.PARALLEL_REQUESTS.html @@ -0,0 +1 @@ +PARALLEL_REQUESTS in wallet_esplora_async - Rust
    pub(crate) const PARALLEL_REQUESTS: usize = 5;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.SEND_AMOUNT.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.SEND_AMOUNT.html new file mode 100644 index 0000000000..440502731a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.SEND_AMOUNT.html @@ -0,0 +1 @@ +SEND_AMOUNT in wallet_esplora_async - Rust
    pub(crate) const SEND_AMOUNT: u64 = 5000;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.STOP_GAP.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.STOP_GAP.html new file mode 100644 index 0000000000..36afeec8d7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/constant.STOP_GAP.html @@ -0,0 +1 @@ +STOP_GAP in wallet_esplora_async - Rust
    pub(crate) const STOP_GAP: usize = 50;
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/fn.main.html new file mode 100644 index 0000000000..36a9b410c4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/fn.main.html @@ -0,0 +1 @@ +main in wallet_esplora_async - Rust

    Function wallet_esplora_async::main

    source ·
    pub(crate) fn main() -> Result<(), Box<dyn Error>>
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/index.html new file mode 100644 index 0000000000..132c54288b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/index.html @@ -0,0 +1 @@ +wallet_esplora_async - Rust

    Constants

    SEND_AMOUNT ðŸ”’
    STOP_GAP ðŸ”’

    Functions

    main ðŸ”’
    \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/sidebar-items.js new file mode 100644 index 0000000000..a6121128e9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"constant":[["PARALLEL_REQUESTS",""],["SEND_AMOUNT",""],["STOP_GAP",""]],"fn":[["main",""]]}; \ No newline at end of file